1d4afb5ceSopenharmony_ci/*
2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation
3d4afb5ceSopenharmony_ci *
4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5d4afb5ceSopenharmony_ci *
6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to
8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the
9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions:
12d4afb5ceSopenharmony_ci *
13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in
14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software.
15d4afb5ceSopenharmony_ci *
16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22d4afb5ceSopenharmony_ci * IN THE SOFTWARE.
23d4afb5ceSopenharmony_ci */
24d4afb5ceSopenharmony_ci
25d4afb5ceSopenharmony_ci#include "private-lib-core.h"
26d4afb5ceSopenharmony_ci#include "private-lib-tls-openssl.h"
27d4afb5ceSopenharmony_ci
28d4afb5ceSopenharmony_ciint openssl_websocket_private_data_index,
29d4afb5ceSopenharmony_ci	   openssl_SSL_CTX_private_data_index;
30d4afb5ceSopenharmony_ci
31d4afb5ceSopenharmony_ci/*
32d4afb5ceSopenharmony_ci * Care: many openssl apis return 1 for success.  These are translated to the
33d4afb5ceSopenharmony_ci * lws convention of 0 for success.
34d4afb5ceSopenharmony_ci */
35d4afb5ceSopenharmony_ci
36d4afb5ceSopenharmony_ciint lws_openssl_describe_cipher(struct lws *wsi)
37d4afb5ceSopenharmony_ci{
38d4afb5ceSopenharmony_ci#if !defined(LWS_WITH_NO_LOGS) && !defined(USE_WOLFSSL)
39d4afb5ceSopenharmony_ci	int np = -1;
40d4afb5ceSopenharmony_ci	SSL *s = wsi->tls.ssl;
41d4afb5ceSopenharmony_ci
42d4afb5ceSopenharmony_ci	SSL_get_cipher_bits(s, &np);
43d4afb5ceSopenharmony_ci	lwsl_info("%s: %s: %s, %s, %d bits, %s\n", __func__, lws_wsi_tag(wsi),
44d4afb5ceSopenharmony_ci			SSL_get_cipher_name(s), SSL_get_cipher(s), np,
45d4afb5ceSopenharmony_ci			SSL_get_cipher_version(s));
46d4afb5ceSopenharmony_ci#endif
47d4afb5ceSopenharmony_ci
48d4afb5ceSopenharmony_ci	return 0;
49d4afb5ceSopenharmony_ci}
50d4afb5ceSopenharmony_ci
51d4afb5ceSopenharmony_ciint lws_ssl_get_error(struct lws *wsi, int n)
52d4afb5ceSopenharmony_ci{
53d4afb5ceSopenharmony_ci	int m;
54d4afb5ceSopenharmony_ci
55d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
56d4afb5ceSopenharmony_ci		return 99;
57d4afb5ceSopenharmony_ci
58d4afb5ceSopenharmony_ci	m = SSL_get_error(wsi->tls.ssl, n);
59d4afb5ceSopenharmony_ci       lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, LWS_ERRNO);
60d4afb5ceSopenharmony_ci
61d4afb5ceSopenharmony_ci       // assert (LWS_ERRNO != 9);
62d4afb5ceSopenharmony_ci
63d4afb5ceSopenharmony_ci	return m;
64d4afb5ceSopenharmony_ci}
65d4afb5ceSopenharmony_ci
66d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
67d4afb5ceSopenharmony_cistatic int
68d4afb5ceSopenharmony_cilws_context_init_ssl_pem_passwd_cb(char *buf, int size, int rwflag,
69d4afb5ceSopenharmony_ci				   void *userdata)
70d4afb5ceSopenharmony_ci{
71d4afb5ceSopenharmony_ci	struct lws_context_creation_info * info =
72d4afb5ceSopenharmony_ci			(struct lws_context_creation_info *)userdata;
73d4afb5ceSopenharmony_ci
74d4afb5ceSopenharmony_ci	strncpy(buf, info->ssl_private_key_password, (unsigned int)size);
75d4afb5ceSopenharmony_ci	buf[size - 1] = '\0';
76d4afb5ceSopenharmony_ci
77d4afb5ceSopenharmony_ci	return (int)strlen(buf);
78d4afb5ceSopenharmony_ci}
79d4afb5ceSopenharmony_ci#endif
80d4afb5ceSopenharmony_ci
81d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
82d4afb5ceSopenharmony_cistatic int
83d4afb5ceSopenharmony_cilws_context_init_ssl_pem_passwd_client_cb(char *buf, int size, int rwflag,
84d4afb5ceSopenharmony_ci					  void *userdata)
85d4afb5ceSopenharmony_ci{
86d4afb5ceSopenharmony_ci	struct lws_context_creation_info * info =
87d4afb5ceSopenharmony_ci			(struct lws_context_creation_info *)userdata;
88d4afb5ceSopenharmony_ci	const char *p = info->ssl_private_key_password;
89d4afb5ceSopenharmony_ci
90d4afb5ceSopenharmony_ci	if (info->client_ssl_private_key_password)
91d4afb5ceSopenharmony_ci		p = info->client_ssl_private_key_password;
92d4afb5ceSopenharmony_ci
93d4afb5ceSopenharmony_ci	strncpy(buf, p, (unsigned int)size);
94d4afb5ceSopenharmony_ci	buf[size - 1] = '\0';
95d4afb5ceSopenharmony_ci
96d4afb5ceSopenharmony_ci	return (int)strlen(buf);
97d4afb5ceSopenharmony_ci}
98d4afb5ceSopenharmony_ci#endif
99d4afb5ceSopenharmony_ci
100d4afb5ceSopenharmony_civoid
101d4afb5ceSopenharmony_cilws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, int is_client,
102d4afb5ceSopenharmony_ci			const struct lws_context_creation_info *info)
103d4afb5ceSopenharmony_ci{
104d4afb5ceSopenharmony_ci	if (
105d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
106d4afb5ceSopenharmony_ci		!info->ssl_private_key_password
107d4afb5ceSopenharmony_ci#endif
108d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) && defined(LWS_WITH_CLIENT)
109d4afb5ceSopenharmony_ci			&&
110d4afb5ceSopenharmony_ci#endif
111d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
112d4afb5ceSopenharmony_ci	    !info->client_ssl_private_key_password
113d4afb5ceSopenharmony_ci#endif
114d4afb5ceSopenharmony_ci	    )
115d4afb5ceSopenharmony_ci		return;
116d4afb5ceSopenharmony_ci	/*
117d4afb5ceSopenharmony_ci	 * password provided, set ssl callback and user data
118d4afb5ceSopenharmony_ci	 * for checking password which will be trigered during
119d4afb5ceSopenharmony_ci	 * SSL_CTX_use_PrivateKey_file function
120d4afb5ceSopenharmony_ci	 */
121d4afb5ceSopenharmony_ci	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
122d4afb5ceSopenharmony_ci	SSL_CTX_set_default_passwd_cb(ssl_ctx, is_client ?
123d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
124d4afb5ceSopenharmony_ci				      lws_context_init_ssl_pem_passwd_client_cb:
125d4afb5ceSopenharmony_ci#else
126d4afb5ceSopenharmony_ci					NULL:
127d4afb5ceSopenharmony_ci#endif
128d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER)
129d4afb5ceSopenharmony_ci				      lws_context_init_ssl_pem_passwd_cb
130d4afb5ceSopenharmony_ci#else
131d4afb5ceSopenharmony_ci				      	NULL
132d4afb5ceSopenharmony_ci#endif
133d4afb5ceSopenharmony_ci				  );
134d4afb5ceSopenharmony_ci}
135d4afb5ceSopenharmony_ci
136d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
137d4afb5ceSopenharmony_cistatic void
138d4afb5ceSopenharmony_cilws_ssl_destroy_client_ctx(struct lws_vhost *vhost)
139d4afb5ceSopenharmony_ci{
140d4afb5ceSopenharmony_ci	if (vhost->tls.user_supplied_ssl_ctx || !vhost->tls.ssl_client_ctx)
141d4afb5ceSopenharmony_ci		return;
142d4afb5ceSopenharmony_ci
143d4afb5ceSopenharmony_ci	if (vhost->tls.tcr && --vhost->tls.tcr->refcount)
144d4afb5ceSopenharmony_ci		return;
145d4afb5ceSopenharmony_ci
146d4afb5ceSopenharmony_ci	SSL_CTX_free(vhost->tls.ssl_client_ctx);
147d4afb5ceSopenharmony_ci	vhost->tls.ssl_client_ctx = NULL;
148d4afb5ceSopenharmony_ci
149d4afb5ceSopenharmony_ci	vhost->context->tls.count_client_contexts--;
150d4afb5ceSopenharmony_ci
151d4afb5ceSopenharmony_ci	if (vhost->tls.tcr) {
152d4afb5ceSopenharmony_ci		lws_dll2_remove(&vhost->tls.tcr->cc_list);
153d4afb5ceSopenharmony_ci		lws_free(vhost->tls.tcr);
154d4afb5ceSopenharmony_ci		vhost->tls.tcr = NULL;
155d4afb5ceSopenharmony_ci	}
156d4afb5ceSopenharmony_ci}
157d4afb5ceSopenharmony_ci#endif
158d4afb5ceSopenharmony_civoid
159d4afb5ceSopenharmony_cilws_ssl_destroy(struct lws_vhost *vhost)
160d4afb5ceSopenharmony_ci{
161d4afb5ceSopenharmony_ci	if (!lws_check_opt(vhost->context->options,
162d4afb5ceSopenharmony_ci			   LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
163d4afb5ceSopenharmony_ci		return;
164d4afb5ceSopenharmony_ci
165d4afb5ceSopenharmony_ci	if (vhost->tls.ssl_ctx)
166d4afb5ceSopenharmony_ci		SSL_CTX_free(vhost->tls.ssl_ctx);
167d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
168d4afb5ceSopenharmony_ci	lws_ssl_destroy_client_ctx(vhost);
169d4afb5ceSopenharmony_ci#endif
170d4afb5ceSopenharmony_ci
171d4afb5ceSopenharmony_ci// after 1.1.0 no need
172d4afb5ceSopenharmony_ci#if (OPENSSL_VERSION_NUMBER <  0x10100000)
173d4afb5ceSopenharmony_ci// <= 1.0.1f = old api, 1.0.1g+ = new api
174d4afb5ceSopenharmony_ci#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
175d4afb5ceSopenharmony_ci	ERR_remove_state(0);
176d4afb5ceSopenharmony_ci#else
177d4afb5ceSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
178d4afb5ceSopenharmony_ci    !defined(LIBRESSL_VERSION_NUMBER) && \
179d4afb5ceSopenharmony_ci    !defined(OPENSSL_IS_BORINGSSL)
180d4afb5ceSopenharmony_ci	ERR_remove_thread_state();
181d4afb5ceSopenharmony_ci#else
182d4afb5ceSopenharmony_ci	ERR_remove_thread_state(NULL);
183d4afb5ceSopenharmony_ci#endif
184d4afb5ceSopenharmony_ci#endif
185d4afb5ceSopenharmony_ci	/* not needed after 1.1.0 */
186d4afb5ceSopenharmony_ci#if  (OPENSSL_VERSION_NUMBER >= 0x10002000) && \
187d4afb5ceSopenharmony_ci     (OPENSSL_VERSION_NUMBER <= 0x10100000)
188d4afb5ceSopenharmony_ci	SSL_COMP_free_compression_methods();
189d4afb5ceSopenharmony_ci#endif
190d4afb5ceSopenharmony_ci	ERR_free_strings();
191d4afb5ceSopenharmony_ci	EVP_cleanup();
192d4afb5ceSopenharmony_ci	CRYPTO_cleanup_all_ex_data();
193d4afb5ceSopenharmony_ci#endif
194d4afb5ceSopenharmony_ci}
195d4afb5ceSopenharmony_ci
196d4afb5ceSopenharmony_ciint
197d4afb5ceSopenharmony_cilws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len)
198d4afb5ceSopenharmony_ci{
199d4afb5ceSopenharmony_ci	struct lws_context *context = wsi->a.context;
200d4afb5ceSopenharmony_ci	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
201d4afb5ceSopenharmony_ci	int n = 0, m;
202d4afb5ceSopenharmony_ci
203d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
204d4afb5ceSopenharmony_ci		return lws_ssl_capable_read_no_ssl(wsi, buf, len);
205d4afb5ceSopenharmony_ci
206d4afb5ceSopenharmony_ci#ifndef WIN32
207d4afb5ceSopenharmony_ci	errno = 0;
208d4afb5ceSopenharmony_ci#else
209d4afb5ceSopenharmony_ci  WSASetLastError(0);
210d4afb5ceSopenharmony_ci#endif
211d4afb5ceSopenharmony_ci	ERR_clear_error();
212d4afb5ceSopenharmony_ci	n = SSL_read(wsi->tls.ssl, buf, (int)(ssize_t)len);
213d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS)
214d4afb5ceSopenharmony_ci	if (!n && errno == LWS_ENOTCONN) {
215d4afb5ceSopenharmony_ci		lwsl_debug("%s: SSL_read ENOTCONN\n", lws_wsi_tag(wsi));
216d4afb5ceSopenharmony_ci		return LWS_SSL_CAPABLE_ERROR;
217d4afb5ceSopenharmony_ci	}
218d4afb5ceSopenharmony_ci#endif
219d4afb5ceSopenharmony_ci
220d4afb5ceSopenharmony_ci	lwsl_debug("%s: SSL_read says %d\n", lws_wsi_tag(wsi), n);
221d4afb5ceSopenharmony_ci	/* manpage: returning 0 means connection shut down
222d4afb5ceSopenharmony_ci	 *
223d4afb5ceSopenharmony_ci	 * 2018-09-10: https://github.com/openssl/openssl/issues/1903
224d4afb5ceSopenharmony_ci	 *
225d4afb5ceSopenharmony_ci	 * So, in summary, if you get a 0 or -1 return from SSL_read() /
226d4afb5ceSopenharmony_ci	 * SSL_write(), you should call SSL_get_error():
227d4afb5ceSopenharmony_ci	 *
228d4afb5ceSopenharmony_ci	 *  - If you get back SSL_ERROR_RETURN_ZERO then you know the connection
229d4afb5ceSopenharmony_ci	 *    has been cleanly shutdown by the peer. To fully close the
230d4afb5ceSopenharmony_ci	 *    connection you may choose to call SSL_shutdown() to send a
231d4afb5ceSopenharmony_ci	 *    close_notify back.
232d4afb5ceSopenharmony_ci	 *
233d4afb5ceSopenharmony_ci	 *  - If you get back SSL_ERROR_SSL then some kind of internal or
234d4afb5ceSopenharmony_ci	 *    protocol error has occurred. More details will be on the SSL error
235d4afb5ceSopenharmony_ci	 *    queue. You can also call SSL_get_shutdown(). If this indicates a
236d4afb5ceSopenharmony_ci	 *    state of SSL_RECEIVED_SHUTDOWN then you know a fatal alert has
237d4afb5ceSopenharmony_ci	 *    been received from the peer (if it had been a close_notify then
238d4afb5ceSopenharmony_ci	 *    SSL_get_error() would have returned SSL_ERROR_RETURN_ZERO).
239d4afb5ceSopenharmony_ci	 *    SSL_ERROR_SSL is considered fatal - you should not call
240d4afb5ceSopenharmony_ci	 *    SSL_shutdown() in this case.
241d4afb5ceSopenharmony_ci	 *
242d4afb5ceSopenharmony_ci	 *  - If you get back SSL_ERROR_SYSCALL then some kind of fatal (i.e.
243d4afb5ceSopenharmony_ci	 *    non-retryable) error has occurred in a system call.
244d4afb5ceSopenharmony_ci	 */
245d4afb5ceSopenharmony_ci	if (n <= 0) {
246d4afb5ceSopenharmony_ci		m = lws_ssl_get_error(wsi, n);
247d4afb5ceSopenharmony_ci               lwsl_debug("%s: ssl err %d errno %d\n", lws_wsi_tag(wsi), m, LWS_ERRNO);
248d4afb5ceSopenharmony_ci		if (m == SSL_ERROR_ZERO_RETURN) /* cleanly shut down */
249d4afb5ceSopenharmony_ci			goto do_err;
250d4afb5ceSopenharmony_ci
251d4afb5ceSopenharmony_ci		if (m == SSL_ERROR_SSL)
252d4afb5ceSopenharmony_ci		    lws_tls_err_describe_clear();
253d4afb5ceSopenharmony_ci
254d4afb5ceSopenharmony_ci		/* hm not retryable.. could be 0 size pkt or error  */
255d4afb5ceSopenharmony_ci
256d4afb5ceSopenharmony_ci		if (m == SSL_ERROR_SSL || m == SSL_ERROR_SYSCALL ||
257d4afb5ceSopenharmony_ci        LWS_ERRNO == LWS_ENOTCONN) {
258d4afb5ceSopenharmony_ci
259d4afb5ceSopenharmony_ci			/* unclean, eg closed conn */
260d4afb5ceSopenharmony_ci
261d4afb5ceSopenharmony_ci			wsi->socket_is_permanently_unusable = 1;
262d4afb5ceSopenharmony_cido_err:
263d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
264d4afb5ceSopenharmony_ci		if (wsi->a.vhost)
265d4afb5ceSopenharmony_ci			lws_metric_event(wsi->a.vhost->mt_traffic_rx,
266d4afb5ceSopenharmony_ci					 METRES_NOGO, 0);
267d4afb5ceSopenharmony_ci#endif
268d4afb5ceSopenharmony_ci			return LWS_SSL_CAPABLE_ERROR;
269d4afb5ceSopenharmony_ci		}
270d4afb5ceSopenharmony_ci
271d4afb5ceSopenharmony_ci		/* retryable? */
272d4afb5ceSopenharmony_ci
273d4afb5ceSopenharmony_ci		if (SSL_want_read(wsi->tls.ssl)) {
274d4afb5ceSopenharmony_ci			lwsl_debug("%s: WANT_READ\n", __func__);
275d4afb5ceSopenharmony_ci			lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi));
276d4afb5ceSopenharmony_ci			return LWS_SSL_CAPABLE_MORE_SERVICE;
277d4afb5ceSopenharmony_ci		}
278d4afb5ceSopenharmony_ci		if (SSL_want_write(wsi->tls.ssl)) {
279d4afb5ceSopenharmony_ci			lwsl_info("%s: WANT_WRITE\n", __func__);
280d4afb5ceSopenharmony_ci			lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi));
281d4afb5ceSopenharmony_ci			wsi->tls_read_wanted_write = 1;
282d4afb5ceSopenharmony_ci			lws_callback_on_writable(wsi);
283d4afb5ceSopenharmony_ci			return LWS_SSL_CAPABLE_MORE_SERVICE;
284d4afb5ceSopenharmony_ci		}
285d4afb5ceSopenharmony_ci
286d4afb5ceSopenharmony_ci		/* keep on trucking it seems */
287d4afb5ceSopenharmony_ci	}
288d4afb5ceSopenharmony_ci
289d4afb5ceSopenharmony_ci#if defined(LWS_TLS_LOG_PLAINTEXT_RX)
290d4afb5ceSopenharmony_ci	/*
291d4afb5ceSopenharmony_ci	 * If using openssl type tls library, this is the earliest point for all
292d4afb5ceSopenharmony_ci	 * paths to dump what was received as decrypted data from the tls tunnel
293d4afb5ceSopenharmony_ci	 */
294d4afb5ceSopenharmony_ci	lwsl_notice("%s: len %d\n", __func__, n);
295d4afb5ceSopenharmony_ci	lwsl_hexdump_notice(buf, (unsigned int)n);
296d4afb5ceSopenharmony_ci#endif
297d4afb5ceSopenharmony_ci
298d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
299d4afb5ceSopenharmony_ci	if (wsi->a.vhost)
300d4afb5ceSopenharmony_ci		lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_GO, (u_mt_t)n);
301d4afb5ceSopenharmony_ci#endif
302d4afb5ceSopenharmony_ci
303d4afb5ceSopenharmony_ci	/*
304d4afb5ceSopenharmony_ci	 * if it was our buffer that limited what we read,
305d4afb5ceSopenharmony_ci	 * check if SSL has additional data pending inside SSL buffers.
306d4afb5ceSopenharmony_ci	 *
307d4afb5ceSopenharmony_ci	 * Because these won't signal at the network layer with POLLIN
308d4afb5ceSopenharmony_ci	 * and if we don't realize, this data will sit there forever
309d4afb5ceSopenharmony_ci	 */
310d4afb5ceSopenharmony_ci	if (n != (int)(ssize_t)len)
311d4afb5ceSopenharmony_ci		goto bail;
312d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
313d4afb5ceSopenharmony_ci		goto bail;
314d4afb5ceSopenharmony_ci
315d4afb5ceSopenharmony_ci	if (SSL_pending(wsi->tls.ssl)) {
316d4afb5ceSopenharmony_ci		if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls))
317d4afb5ceSopenharmony_ci			lws_dll2_add_head(&wsi->tls.dll_pending_tls,
318d4afb5ceSopenharmony_ci					  &pt->tls.dll_pending_tls_owner);
319d4afb5ceSopenharmony_ci	} else
320d4afb5ceSopenharmony_ci		__lws_ssl_remove_wsi_from_buffered_list(wsi);
321d4afb5ceSopenharmony_ci
322d4afb5ceSopenharmony_ci	return n;
323d4afb5ceSopenharmony_cibail:
324d4afb5ceSopenharmony_ci	lws_ssl_remove_wsi_from_buffered_list(wsi);
325d4afb5ceSopenharmony_ci
326d4afb5ceSopenharmony_ci	return n;
327d4afb5ceSopenharmony_ci}
328d4afb5ceSopenharmony_ci
329d4afb5ceSopenharmony_ciint
330d4afb5ceSopenharmony_cilws_ssl_pending(struct lws *wsi)
331d4afb5ceSopenharmony_ci{
332d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
333d4afb5ceSopenharmony_ci		return 0;
334d4afb5ceSopenharmony_ci
335d4afb5ceSopenharmony_ci	return SSL_pending(wsi->tls.ssl);
336d4afb5ceSopenharmony_ci}
337d4afb5ceSopenharmony_ci
338d4afb5ceSopenharmony_ciint
339d4afb5ceSopenharmony_cilws_ssl_capable_write(struct lws *wsi, unsigned char *buf, size_t len)
340d4afb5ceSopenharmony_ci{
341d4afb5ceSopenharmony_ci	int n, m;
342d4afb5ceSopenharmony_ci
343d4afb5ceSopenharmony_ci
344d4afb5ceSopenharmony_ci#if defined(LWS_TLS_LOG_PLAINTEXT_TX)
345d4afb5ceSopenharmony_ci	/*
346d4afb5ceSopenharmony_ci	 * If using OpenSSL type tls library, this is the last point for all
347d4afb5ceSopenharmony_ci	 * paths before sending data into the tls tunnel, where you can dump it
348d4afb5ceSopenharmony_ci	 * and see what is being sent.
349d4afb5ceSopenharmony_ci	 */
350d4afb5ceSopenharmony_ci	lwsl_notice("%s: len %u\n", __func__, (unsigned int)len);
351d4afb5ceSopenharmony_ci	lwsl_hexdump_notice(buf, len);
352d4afb5ceSopenharmony_ci#endif
353d4afb5ceSopenharmony_ci
354d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
355d4afb5ceSopenharmony_ci		return lws_ssl_capable_write_no_ssl(wsi, buf, len);
356d4afb5ceSopenharmony_ci
357d4afb5ceSopenharmony_ci	errno = 0;
358d4afb5ceSopenharmony_ci	ERR_clear_error();
359d4afb5ceSopenharmony_ci	n = SSL_write(wsi->tls.ssl, buf, (int)(ssize_t)len);
360d4afb5ceSopenharmony_ci	if (n > 0) {
361d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
362d4afb5ceSopenharmony_ci		if (wsi->a.vhost)
363d4afb5ceSopenharmony_ci			lws_metric_event(wsi->a.vhost->mt_traffic_tx,
364d4afb5ceSopenharmony_ci					 METRES_GO, (u_mt_t)n);
365d4afb5ceSopenharmony_ci#endif
366d4afb5ceSopenharmony_ci		return n;
367d4afb5ceSopenharmony_ci	}
368d4afb5ceSopenharmony_ci
369d4afb5ceSopenharmony_ci	m = lws_ssl_get_error(wsi, n);
370d4afb5ceSopenharmony_ci	if (m != SSL_ERROR_SYSCALL) {
371d4afb5ceSopenharmony_ci		if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) {
372d4afb5ceSopenharmony_ci			lwsl_notice("%s: want read\n", __func__);
373d4afb5ceSopenharmony_ci
374d4afb5ceSopenharmony_ci			return LWS_SSL_CAPABLE_MORE_SERVICE;
375d4afb5ceSopenharmony_ci		}
376d4afb5ceSopenharmony_ci
377d4afb5ceSopenharmony_ci		if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) {
378d4afb5ceSopenharmony_ci			lws_set_blocking_send(wsi);
379d4afb5ceSopenharmony_ci
380d4afb5ceSopenharmony_ci			lwsl_debug("%s: want write\n", __func__);
381d4afb5ceSopenharmony_ci
382d4afb5ceSopenharmony_ci			return LWS_SSL_CAPABLE_MORE_SERVICE;
383d4afb5ceSopenharmony_ci		}
384d4afb5ceSopenharmony_ci	}
385d4afb5ceSopenharmony_ci
386d4afb5ceSopenharmony_ci	lwsl_debug("%s failed: %s\n",__func__, ERR_error_string((unsigned int)m, NULL));
387d4afb5ceSopenharmony_ci	lws_tls_err_describe_clear();
388d4afb5ceSopenharmony_ci
389d4afb5ceSopenharmony_ci	wsi->socket_is_permanently_unusable = 1;
390d4afb5ceSopenharmony_ci
391d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS)
392d4afb5ceSopenharmony_ci		if (wsi->a.vhost)
393d4afb5ceSopenharmony_ci			lws_metric_event(wsi->a.vhost->mt_traffic_tx,
394d4afb5ceSopenharmony_ci					 METRES_NOGO, 0);
395d4afb5ceSopenharmony_ci#endif
396d4afb5ceSopenharmony_ci
397d4afb5ceSopenharmony_ci	return LWS_SSL_CAPABLE_ERROR;
398d4afb5ceSopenharmony_ci}
399d4afb5ceSopenharmony_ci
400d4afb5ceSopenharmony_civoid
401d4afb5ceSopenharmony_cilws_ssl_info_callback(const SSL *ssl, int where, int ret)
402d4afb5ceSopenharmony_ci{
403d4afb5ceSopenharmony_ci	struct lws *wsi;
404d4afb5ceSopenharmony_ci	struct lws_context *context;
405d4afb5ceSopenharmony_ci	struct lws_ssl_info si;
406d4afb5ceSopenharmony_ci	int fd;
407d4afb5ceSopenharmony_ci
408d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL
409d4afb5ceSopenharmony_ci	context = (struct lws_context *)SSL_CTX_get_ex_data(
410d4afb5ceSopenharmony_ci					SSL_get_SSL_CTX(ssl),
411d4afb5ceSopenharmony_ci					openssl_SSL_CTX_private_data_index);
412d4afb5ceSopenharmony_ci#else
413d4afb5ceSopenharmony_ci	context = (struct lws_context *)SSL_CTX_get_ex_data(
414d4afb5ceSopenharmony_ci					SSL_get_SSL_CTX((SSL*) ssl),
415d4afb5ceSopenharmony_ci					openssl_SSL_CTX_private_data_index);
416d4afb5ceSopenharmony_ci#endif
417d4afb5ceSopenharmony_ci	if (!context)
418d4afb5ceSopenharmony_ci		return;
419d4afb5ceSopenharmony_ci
420d4afb5ceSopenharmony_ci	fd = SSL_get_fd(ssl);
421d4afb5ceSopenharmony_ci	if (fd < 0 || (fd - lws_plat_socket_offset()) < 0)
422d4afb5ceSopenharmony_ci		return;
423d4afb5ceSopenharmony_ci
424d4afb5ceSopenharmony_ci	wsi = wsi_from_fd(context, fd);
425d4afb5ceSopenharmony_ci	if (!wsi)
426d4afb5ceSopenharmony_ci		return;
427d4afb5ceSopenharmony_ci
428d4afb5ceSopenharmony_ci	if (!(where & wsi->a.vhost->tls.ssl_info_event_mask))
429d4afb5ceSopenharmony_ci		return;
430d4afb5ceSopenharmony_ci
431d4afb5ceSopenharmony_ci	si.where = where;
432d4afb5ceSopenharmony_ci	si.ret = ret;
433d4afb5ceSopenharmony_ci
434d4afb5ceSopenharmony_ci	if (user_callback_handle_rxflow(wsi->a.protocol->callback,
435d4afb5ceSopenharmony_ci					wsi, LWS_CALLBACK_SSL_INFO,
436d4afb5ceSopenharmony_ci					wsi->user_space, &si, 0))
437d4afb5ceSopenharmony_ci		lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
438d4afb5ceSopenharmony_ci}
439d4afb5ceSopenharmony_ci
440d4afb5ceSopenharmony_ci
441d4afb5ceSopenharmony_ciint
442d4afb5ceSopenharmony_cilws_ssl_close(struct lws *wsi)
443d4afb5ceSopenharmony_ci{
444d4afb5ceSopenharmony_ci	lws_sockfd_type n;
445d4afb5ceSopenharmony_ci
446d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
447d4afb5ceSopenharmony_ci		return 0; /* not handled */
448d4afb5ceSopenharmony_ci
449d4afb5ceSopenharmony_ci#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
450d4afb5ceSopenharmony_ci	/* kill ssl callbacks, because we will remove the fd from the
451d4afb5ceSopenharmony_ci	 * table linking it to the wsi
452d4afb5ceSopenharmony_ci	 */
453d4afb5ceSopenharmony_ci	if (wsi->a.vhost->tls.ssl_info_event_mask)
454d4afb5ceSopenharmony_ci		SSL_set_info_callback(wsi->tls.ssl, NULL);
455d4afb5ceSopenharmony_ci#endif
456d4afb5ceSopenharmony_ci
457d4afb5ceSopenharmony_ci#if defined(LWS_TLS_SYNTHESIZE_CB)
458d4afb5ceSopenharmony_ci	lws_sul_cancel(&wsi->tls.sul_cb_synth);
459d4afb5ceSopenharmony_ci	/*
460d4afb5ceSopenharmony_ci	 * ... check the session in case it did not live long enough to get
461d4afb5ceSopenharmony_ci	 * the scheduled callback to sample it
462d4afb5ceSopenharmony_ci	 */
463d4afb5ceSopenharmony_ci	lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth);
464d4afb5ceSopenharmony_ci#endif
465d4afb5ceSopenharmony_ci
466d4afb5ceSopenharmony_ci	n = SSL_get_fd(wsi->tls.ssl);
467d4afb5ceSopenharmony_ci	if (!wsi->socket_is_permanently_unusable)
468d4afb5ceSopenharmony_ci		SSL_shutdown(wsi->tls.ssl);
469d4afb5ceSopenharmony_ci	compatible_close(n);
470d4afb5ceSopenharmony_ci	SSL_free(wsi->tls.ssl);
471d4afb5ceSopenharmony_ci	wsi->tls.ssl = NULL;
472d4afb5ceSopenharmony_ci
473d4afb5ceSopenharmony_ci	lws_tls_restrict_return(wsi);
474d4afb5ceSopenharmony_ci
475d4afb5ceSopenharmony_ci	// lwsl_notice("%s: ssl restr %d, simul %d\n", __func__,
476d4afb5ceSopenharmony_ci	//		wsi->a.context->simultaneous_ssl_restriction,
477d4afb5ceSopenharmony_ci	//		wsi->a.context->simultaneous_ssl);
478d4afb5ceSopenharmony_ci
479d4afb5ceSopenharmony_ci	return 1; /* handled */
480d4afb5ceSopenharmony_ci}
481d4afb5ceSopenharmony_ci
482d4afb5ceSopenharmony_civoid
483d4afb5ceSopenharmony_cilws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
484d4afb5ceSopenharmony_ci{
485d4afb5ceSopenharmony_ci	if (vhost->tls.ssl_ctx)
486d4afb5ceSopenharmony_ci		SSL_CTX_free(vhost->tls.ssl_ctx);
487d4afb5ceSopenharmony_ci
488d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CLIENT)
489d4afb5ceSopenharmony_ci	lws_ssl_destroy_client_ctx(vhost);
490d4afb5ceSopenharmony_ci#endif
491d4afb5ceSopenharmony_ci
492d4afb5ceSopenharmony_ci#if defined(LWS_WITH_ACME)
493d4afb5ceSopenharmony_ci	lws_tls_acme_sni_cert_destroy(vhost);
494d4afb5ceSopenharmony_ci#endif
495d4afb5ceSopenharmony_ci}
496d4afb5ceSopenharmony_ci
497d4afb5ceSopenharmony_civoid
498d4afb5ceSopenharmony_cilws_ssl_context_destroy(struct lws_context *context)
499d4afb5ceSopenharmony_ci{
500d4afb5ceSopenharmony_ci// after 1.1.0 no need
501d4afb5ceSopenharmony_ci#if (OPENSSL_VERSION_NUMBER <  0x10100000)
502d4afb5ceSopenharmony_ci// <= 1.0.1f = old api, 1.0.1g+ = new api
503d4afb5ceSopenharmony_ci#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
504d4afb5ceSopenharmony_ci	ERR_remove_state(0);
505d4afb5ceSopenharmony_ci#else
506d4afb5ceSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
507d4afb5ceSopenharmony_ci    !defined(LIBRESSL_VERSION_NUMBER) && \
508d4afb5ceSopenharmony_ci    !defined(OPENSSL_IS_BORINGSSL)
509d4afb5ceSopenharmony_ci	ERR_remove_thread_state();
510d4afb5ceSopenharmony_ci#else
511d4afb5ceSopenharmony_ci	ERR_remove_thread_state(NULL);
512d4afb5ceSopenharmony_ci#endif
513d4afb5ceSopenharmony_ci#endif
514d4afb5ceSopenharmony_ci	// after 1.1.0 no need
515d4afb5ceSopenharmony_ci#if  (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000)
516d4afb5ceSopenharmony_ci	SSL_COMP_free_compression_methods();
517d4afb5ceSopenharmony_ci#endif
518d4afb5ceSopenharmony_ci	ERR_free_strings();
519d4afb5ceSopenharmony_ci	EVP_cleanup();
520d4afb5ceSopenharmony_ci	CRYPTO_cleanup_all_ex_data();
521d4afb5ceSopenharmony_ci#endif
522d4afb5ceSopenharmony_ci}
523d4afb5ceSopenharmony_ci
524d4afb5ceSopenharmony_cilws_tls_ctx *
525d4afb5ceSopenharmony_cilws_tls_ctx_from_wsi(struct lws *wsi)
526d4afb5ceSopenharmony_ci{
527d4afb5ceSopenharmony_ci	if (!wsi->tls.ssl)
528d4afb5ceSopenharmony_ci		return NULL;
529d4afb5ceSopenharmony_ci
530d4afb5ceSopenharmony_ci	return SSL_get_SSL_CTX(wsi->tls.ssl);
531d4afb5ceSopenharmony_ci}
532d4afb5ceSopenharmony_ci
533d4afb5ceSopenharmony_cienum lws_ssl_capable_status
534d4afb5ceSopenharmony_ci__lws_tls_shutdown(struct lws *wsi)
535d4afb5ceSopenharmony_ci{
536d4afb5ceSopenharmony_ci	int n;
537d4afb5ceSopenharmony_ci
538d4afb5ceSopenharmony_ci#ifndef WIN32
539d4afb5ceSopenharmony_ci	errno = 0;
540d4afb5ceSopenharmony_ci#else
541d4afb5ceSopenharmony_ci  WSASetLastError(0);
542d4afb5ceSopenharmony_ci#endif
543d4afb5ceSopenharmony_ci	ERR_clear_error();
544d4afb5ceSopenharmony_ci	n = SSL_shutdown(wsi->tls.ssl);
545d4afb5ceSopenharmony_ci	lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd);
546d4afb5ceSopenharmony_ci	switch (n) {
547d4afb5ceSopenharmony_ci	case 1: /* successful completion */
548d4afb5ceSopenharmony_ci		n = shutdown(wsi->desc.sockfd, SHUT_WR);
549d4afb5ceSopenharmony_ci		return LWS_SSL_CAPABLE_DONE;
550d4afb5ceSopenharmony_ci
551d4afb5ceSopenharmony_ci	case 0: /* needs a retry */
552d4afb5ceSopenharmony_ci		__lws_change_pollfd(wsi, 0, LWS_POLLIN);
553d4afb5ceSopenharmony_ci		return LWS_SSL_CAPABLE_MORE_SERVICE;
554d4afb5ceSopenharmony_ci
555d4afb5ceSopenharmony_ci	default: /* fatal error, or WANT */
556d4afb5ceSopenharmony_ci		n = SSL_get_error(wsi->tls.ssl, n);
557d4afb5ceSopenharmony_ci		if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) {
558d4afb5ceSopenharmony_ci			if (SSL_want_read(wsi->tls.ssl)) {
559d4afb5ceSopenharmony_ci				lwsl_debug("(wants read)\n");
560d4afb5ceSopenharmony_ci				__lws_change_pollfd(wsi, 0, LWS_POLLIN);
561d4afb5ceSopenharmony_ci				return LWS_SSL_CAPABLE_MORE_SERVICE_READ;
562d4afb5ceSopenharmony_ci			}
563d4afb5ceSopenharmony_ci			if (SSL_want_write(wsi->tls.ssl)) {
564d4afb5ceSopenharmony_ci				lwsl_debug("(wants write)\n");
565d4afb5ceSopenharmony_ci				__lws_change_pollfd(wsi, 0, LWS_POLLOUT);
566d4afb5ceSopenharmony_ci				return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE;
567d4afb5ceSopenharmony_ci			}
568d4afb5ceSopenharmony_ci		}
569d4afb5ceSopenharmony_ci		return LWS_SSL_CAPABLE_ERROR;
570d4afb5ceSopenharmony_ci	}
571d4afb5ceSopenharmony_ci}
572d4afb5ceSopenharmony_ci
573d4afb5ceSopenharmony_ci
574d4afb5ceSopenharmony_cistatic int
575d4afb5ceSopenharmony_citops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt)
576d4afb5ceSopenharmony_ci{
577d4afb5ceSopenharmony_ci	return lws_tls_fake_POLLIN_for_buffered(pt);
578d4afb5ceSopenharmony_ci}
579d4afb5ceSopenharmony_ci
580d4afb5ceSopenharmony_ciconst struct lws_tls_ops tls_ops_openssl = {
581d4afb5ceSopenharmony_ci	/* fake_POLLIN_for_buffered */	tops_fake_POLLIN_for_buffered_openssl,
582d4afb5ceSopenharmony_ci};
583