xref: /aosp_15_r20/external/libwebsockets/lib/tls/tls.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-tls.h"
27*1c60b9acSAndroid Build Coastguard Worker 
28*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_NETWORK)
29*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
30*1c60b9acSAndroid Build Coastguard Worker 				  OPENSSL_VERSION_NUMBER >= 0x10002000L)
31*1c60b9acSAndroid Build Coastguard Worker static int
alpn_cb(SSL * s,const unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)32*1c60b9acSAndroid Build Coastguard Worker alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
33*1c60b9acSAndroid Build Coastguard Worker 	const unsigned char *in, unsigned int inlen, void *arg)
34*1c60b9acSAndroid Build Coastguard Worker {
35*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_MBEDTLS)
36*1c60b9acSAndroid Build Coastguard Worker 	struct alpn_ctx *alpn_ctx = (struct alpn_ctx *)arg;
37*1c60b9acSAndroid Build Coastguard Worker 
38*1c60b9acSAndroid Build Coastguard Worker 	if (SSL_select_next_proto((unsigned char **)out, outlen, alpn_ctx->data,
39*1c60b9acSAndroid Build Coastguard Worker 				  alpn_ctx->len, in, inlen) !=
40*1c60b9acSAndroid Build Coastguard Worker 	    OPENSSL_NPN_NEGOTIATED)
41*1c60b9acSAndroid Build Coastguard Worker 		return SSL_TLSEXT_ERR_NOACK;
42*1c60b9acSAndroid Build Coastguard Worker #endif
43*1c60b9acSAndroid Build Coastguard Worker 
44*1c60b9acSAndroid Build Coastguard Worker 	return SSL_TLSEXT_ERR_OK;
45*1c60b9acSAndroid Build Coastguard Worker }
46*1c60b9acSAndroid Build Coastguard Worker #endif
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_restrict_borrow(struct lws * wsi)49*1c60b9acSAndroid Build Coastguard Worker lws_tls_restrict_borrow(struct lws *wsi)
50*1c60b9acSAndroid Build Coastguard Worker {
51*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *cx = wsi->a.context;
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker 	if (cx->simultaneous_ssl_restriction &&
54*1c60b9acSAndroid Build Coastguard Worker 	    cx->simultaneous_ssl >= cx->simultaneous_ssl_restriction) {
55*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: tls connection limit %d\n", __func__,
56*1c60b9acSAndroid Build Coastguard Worker 			    cx->simultaneous_ssl);
57*1c60b9acSAndroid Build Coastguard Worker 		return 1;
58*1c60b9acSAndroid Build Coastguard Worker 	}
59*1c60b9acSAndroid Build Coastguard Worker 
60*1c60b9acSAndroid Build Coastguard Worker 	if (cx->simultaneous_ssl_handshake_restriction &&
61*1c60b9acSAndroid Build Coastguard Worker 	    cx->simultaneous_ssl_handshake >=
62*1c60b9acSAndroid Build Coastguard Worker 			    cx->simultaneous_ssl_handshake_restriction) {
63*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: tls handshake limit %d\n", __func__,
64*1c60b9acSAndroid Build Coastguard Worker 			    cx->simultaneous_ssl);
65*1c60b9acSAndroid Build Coastguard Worker 		return 1;
66*1c60b9acSAndroid Build Coastguard Worker 	}
67*1c60b9acSAndroid Build Coastguard Worker 
68*1c60b9acSAndroid Build Coastguard Worker 	cx->simultaneous_ssl++;
69*1c60b9acSAndroid Build Coastguard Worker 	cx->simultaneous_ssl_handshake++;
70*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls_borrowed_hs = 1;
71*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls_borrowed = 1;
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %d -> %d\n", __func__,
74*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl - 1,
75*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl);
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker 	assert(!cx->simultaneous_ssl_restriction ||
78*1c60b9acSAndroid Build Coastguard Worker 			cx->simultaneous_ssl <=
79*1c60b9acSAndroid Build Coastguard Worker 				cx->simultaneous_ssl_restriction);
80*1c60b9acSAndroid Build Coastguard Worker 	assert(!cx->simultaneous_ssl_handshake_restriction ||
81*1c60b9acSAndroid Build Coastguard Worker 			cx->simultaneous_ssl_handshake <=
82*1c60b9acSAndroid Build Coastguard Worker 				cx->simultaneous_ssl_handshake_restriction);
83*1c60b9acSAndroid Build Coastguard Worker 
84*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
85*1c60b9acSAndroid Build Coastguard Worker 	lws_gate_accepts(cx,
86*1c60b9acSAndroid Build Coastguard Worker 			(cx->simultaneous_ssl_restriction &&
87*1c60b9acSAndroid Build Coastguard Worker 			 cx->simultaneous_ssl == cx->simultaneous_ssl_restriction) ||
88*1c60b9acSAndroid Build Coastguard Worker 			(cx->simultaneous_ssl_handshake_restriction &&
89*1c60b9acSAndroid Build Coastguard Worker 			 cx->simultaneous_ssl_handshake == cx->simultaneous_ssl_handshake_restriction));
90*1c60b9acSAndroid Build Coastguard Worker #endif
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker 	return 0;
93*1c60b9acSAndroid Build Coastguard Worker }
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker static void
_lws_tls_restrict_return(struct lws * wsi)96*1c60b9acSAndroid Build Coastguard Worker _lws_tls_restrict_return(struct lws *wsi)
97*1c60b9acSAndroid Build Coastguard Worker {
98*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
99*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *cx = wsi->a.context;
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 	assert(cx->simultaneous_ssl_handshake >= 0);
102*1c60b9acSAndroid Build Coastguard Worker 	assert(cx->simultaneous_ssl >= 0);
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker 	lws_gate_accepts(cx,
105*1c60b9acSAndroid Build Coastguard Worker 			(cx->simultaneous_ssl_restriction &&
106*1c60b9acSAndroid Build Coastguard Worker 			 cx->simultaneous_ssl == cx->simultaneous_ssl_restriction) ||
107*1c60b9acSAndroid Build Coastguard Worker 			(cx->simultaneous_ssl_handshake_restriction &&
108*1c60b9acSAndroid Build Coastguard Worker 			 cx->simultaneous_ssl_handshake == cx->simultaneous_ssl_handshake_restriction));
109*1c60b9acSAndroid Build Coastguard Worker #endif
110*1c60b9acSAndroid Build Coastguard Worker }
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_restrict_return_handshake(struct lws * wsi)113*1c60b9acSAndroid Build Coastguard Worker lws_tls_restrict_return_handshake(struct lws *wsi)
114*1c60b9acSAndroid Build Coastguard Worker {
115*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *cx = wsi->a.context;
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 	/* we're just returning the hs part */
118*1c60b9acSAndroid Build Coastguard Worker 
119*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->tls_borrowed_hs)
120*1c60b9acSAndroid Build Coastguard Worker 		return;
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls_borrowed_hs = 0; /* return it one time per wsi */
123*1c60b9acSAndroid Build Coastguard Worker 	cx->simultaneous_ssl_handshake--;
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s:  %d -> %d\n", __func__,
126*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl_handshake + 1,
127*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl_handshake);
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 	_lws_tls_restrict_return(wsi);
130*1c60b9acSAndroid Build Coastguard Worker }
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker void
lws_tls_restrict_return(struct lws * wsi)133*1c60b9acSAndroid Build Coastguard Worker lws_tls_restrict_return(struct lws *wsi)
134*1c60b9acSAndroid Build Coastguard Worker {
135*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *cx = wsi->a.context;
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->tls_borrowed)
138*1c60b9acSAndroid Build Coastguard Worker 		return;
139*1c60b9acSAndroid Build Coastguard Worker 
140*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls_borrowed = 0;
141*1c60b9acSAndroid Build Coastguard Worker 	cx->simultaneous_ssl--;
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: %d -> %d\n", __func__,
144*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl + 1,
145*1c60b9acSAndroid Build Coastguard Worker 		  cx->simultaneous_ssl);
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 	/* We're returning everything, even if hs didn't complete */
148*1c60b9acSAndroid Build Coastguard Worker 
149*1c60b9acSAndroid Build Coastguard Worker 	if (wsi->tls_borrowed_hs)
150*1c60b9acSAndroid Build Coastguard Worker 		lws_tls_restrict_return_handshake(wsi);
151*1c60b9acSAndroid Build Coastguard Worker 	else
152*1c60b9acSAndroid Build Coastguard Worker 		_lws_tls_restrict_return(wsi);
153*1c60b9acSAndroid Build Coastguard Worker }
154*1c60b9acSAndroid Build Coastguard Worker 
155*1c60b9acSAndroid Build Coastguard Worker void
lws_context_init_alpn(struct lws_vhost * vhost)156*1c60b9acSAndroid Build Coastguard Worker lws_context_init_alpn(struct lws_vhost *vhost)
157*1c60b9acSAndroid Build Coastguard Worker {
158*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
159*1c60b9acSAndroid Build Coastguard Worker 				  OPENSSL_VERSION_NUMBER >= 0x10002000L)
160*1c60b9acSAndroid Build Coastguard Worker 	const char *alpn_comma = vhost->context->tls.alpn_default;
161*1c60b9acSAndroid Build Coastguard Worker 
162*1c60b9acSAndroid Build Coastguard Worker 	if (vhost->tls.alpn)
163*1c60b9acSAndroid Build Coastguard Worker 		alpn_comma = vhost->tls.alpn;
164*1c60b9acSAndroid Build Coastguard Worker 
165*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info(" Server '%s' advertising ALPN: %s\n",
166*1c60b9acSAndroid Build Coastguard Worker 		    vhost->name, alpn_comma);
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	vhost->tls.alpn_ctx.len = (uint8_t)lws_alpn_comma_to_openssl(alpn_comma,
169*1c60b9acSAndroid Build Coastguard Worker 					vhost->tls.alpn_ctx.data,
170*1c60b9acSAndroid Build Coastguard Worker 					sizeof(vhost->tls.alpn_ctx.data) - 1);
171*1c60b9acSAndroid Build Coastguard Worker 
172*1c60b9acSAndroid Build Coastguard Worker 	SSL_CTX_set_alpn_select_cb(vhost->tls.ssl_ctx, alpn_cb,
173*1c60b9acSAndroid Build Coastguard Worker 				   &vhost->tls.alpn_ctx);
174*1c60b9acSAndroid Build Coastguard Worker #else
175*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err(" HTTP2 / ALPN configured "
176*1c60b9acSAndroid Build Coastguard Worker 		 "but not supported by OpenSSL 0x%lx\n",
177*1c60b9acSAndroid Build Coastguard Worker 		 OPENSSL_VERSION_NUMBER);
178*1c60b9acSAndroid Build Coastguard Worker #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
179*1c60b9acSAndroid Build Coastguard Worker }
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_server_conn_alpn(struct lws * wsi)182*1c60b9acSAndroid Build Coastguard Worker lws_tls_server_conn_alpn(struct lws *wsi)
183*1c60b9acSAndroid Build Coastguard Worker {
184*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \
185*1c60b9acSAndroid Build Coastguard Worker 				  OPENSSL_VERSION_NUMBER >= 0x10002000L)
186*1c60b9acSAndroid Build Coastguard Worker 	const unsigned char *name = NULL;
187*1c60b9acSAndroid Build Coastguard Worker 	char cstr[10];
188*1c60b9acSAndroid Build Coastguard Worker 	unsigned len;
189*1c60b9acSAndroid Build Coastguard Worker 
190*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s\n", __func__);
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker 	if (!wsi->tls.ssl) {
193*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: non-ssl\n", __func__);
194*1c60b9acSAndroid Build Coastguard Worker 		return 0;
195*1c60b9acSAndroid Build Coastguard Worker 	}
196*1c60b9acSAndroid Build Coastguard Worker 
197*1c60b9acSAndroid Build Coastguard Worker 	SSL_get0_alpn_selected(wsi->tls.ssl, &name, &len);
198*1c60b9acSAndroid Build Coastguard Worker 	if (!len) {
199*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("no ALPN upgrade\n");
200*1c60b9acSAndroid Build Coastguard Worker 		return 0;
201*1c60b9acSAndroid Build Coastguard Worker 	}
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	if (len > sizeof(cstr) - 1)
204*1c60b9acSAndroid Build Coastguard Worker 		len = sizeof(cstr) - 1;
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 	memcpy(cstr, name, len);
207*1c60b9acSAndroid Build Coastguard Worker 	cstr[len] = '\0';
208*1c60b9acSAndroid Build Coastguard Worker 
209*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: negotiated '%s' using ALPN\n", __func__, cstr);
210*1c60b9acSAndroid Build Coastguard Worker 	wsi->tls.use_ssl |= LCCSCF_USE_SSL;
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 	return lws_role_call_alpn_negotiated(wsi, (const char *)cstr);
213*1c60b9acSAndroid Build Coastguard Worker #else
214*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: openssl too old\n", __func__);
215*1c60b9acSAndroid Build Coastguard Worker #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
216*1c60b9acSAndroid Build Coastguard Worker 
217*1c60b9acSAndroid Build Coastguard Worker 	return 0;
218*1c60b9acSAndroid Build Coastguard Worker }
219*1c60b9acSAndroid Build Coastguard Worker #endif
220*1c60b9acSAndroid Build Coastguard Worker 
221*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
222*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_PLAT_FREERTOS) && !defined(LWS_AMAZON_RTOS)
alloc_file(struct lws_context * context,const char * filename,uint8_t ** buf,lws_filepos_t * amount)223*1c60b9acSAndroid Build Coastguard Worker int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
224*1c60b9acSAndroid Build Coastguard Worker 	       lws_filepos_t *amount)
225*1c60b9acSAndroid Build Coastguard Worker {
226*1c60b9acSAndroid Build Coastguard Worker 	nvs_handle nvh;
227*1c60b9acSAndroid Build Coastguard Worker 	size_t s;
228*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 	ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
231*1c60b9acSAndroid Build Coastguard Worker 	if (nvs_get_blob(nvh, filename, NULL, &s) != ESP_OK) {
232*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
233*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
234*1c60b9acSAndroid Build Coastguard Worker 	}
235*1c60b9acSAndroid Build Coastguard Worker 	*buf = lws_malloc(s + 1, "alloc_file");
236*1c60b9acSAndroid Build Coastguard Worker 	if (!*buf) {
237*1c60b9acSAndroid Build Coastguard Worker 		n = 2;
238*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
239*1c60b9acSAndroid Build Coastguard Worker 	}
240*1c60b9acSAndroid Build Coastguard Worker 	if (nvs_get_blob(nvh, filename, (char *)*buf, &s) != ESP_OK) {
241*1c60b9acSAndroid Build Coastguard Worker 		lws_free(*buf);
242*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
243*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
244*1c60b9acSAndroid Build Coastguard Worker 	}
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	*amount = s;
247*1c60b9acSAndroid Build Coastguard Worker 	(*buf)[s] = '\0';
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: nvs: read %s, %d bytes\n", __func__, filename, (int)s);
250*1c60b9acSAndroid Build Coastguard Worker 
251*1c60b9acSAndroid Build Coastguard Worker bail:
252*1c60b9acSAndroid Build Coastguard Worker 	nvs_close(nvh);
253*1c60b9acSAndroid Build Coastguard Worker 
254*1c60b9acSAndroid Build Coastguard Worker 	return n;
255*1c60b9acSAndroid Build Coastguard Worker }
256*1c60b9acSAndroid Build Coastguard Worker #else
alloc_file(struct lws_context * context,const char * filename,uint8_t ** buf,lws_filepos_t * amount)257*1c60b9acSAndroid Build Coastguard Worker int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
258*1c60b9acSAndroid Build Coastguard Worker 		lws_filepos_t *amount)
259*1c60b9acSAndroid Build Coastguard Worker {
260*1c60b9acSAndroid Build Coastguard Worker 	FILE *f;
261*1c60b9acSAndroid Build Coastguard Worker 	size_t s;
262*1c60b9acSAndroid Build Coastguard Worker 	ssize_t m;
263*1c60b9acSAndroid Build Coastguard Worker 	int n = 0;
264*1c60b9acSAndroid Build Coastguard Worker 
265*1c60b9acSAndroid Build Coastguard Worker 	f = fopen(filename, "rb");
266*1c60b9acSAndroid Build Coastguard Worker 	if (f == NULL) {
267*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
268*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
269*1c60b9acSAndroid Build Coastguard Worker 	}
270*1c60b9acSAndroid Build Coastguard Worker 
271*1c60b9acSAndroid Build Coastguard Worker 	if (fseek(f, 0, SEEK_END) != 0) {
272*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
273*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
274*1c60b9acSAndroid Build Coastguard Worker 	}
275*1c60b9acSAndroid Build Coastguard Worker 
276*1c60b9acSAndroid Build Coastguard Worker 	m = (ssize_t)ftell(f);
277*1c60b9acSAndroid Build Coastguard Worker 	if (m == -1l) {
278*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
279*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
280*1c60b9acSAndroid Build Coastguard Worker 	}
281*1c60b9acSAndroid Build Coastguard Worker 	s = (size_t)m;
282*1c60b9acSAndroid Build Coastguard Worker 
283*1c60b9acSAndroid Build Coastguard Worker 	if (fseek(f, 0, SEEK_SET) != 0) {
284*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
285*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
286*1c60b9acSAndroid Build Coastguard Worker 	}
287*1c60b9acSAndroid Build Coastguard Worker 
288*1c60b9acSAndroid Build Coastguard Worker 	*buf = lws_malloc(s + 1, "alloc_file");
289*1c60b9acSAndroid Build Coastguard Worker 	if (!*buf) {
290*1c60b9acSAndroid Build Coastguard Worker 		n = 2;
291*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
292*1c60b9acSAndroid Build Coastguard Worker 	}
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker 	if (fread(*buf, s, 1, f) != 1) {
295*1c60b9acSAndroid Build Coastguard Worker 		lws_free(*buf);
296*1c60b9acSAndroid Build Coastguard Worker 		n = 1;
297*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
298*1c60b9acSAndroid Build Coastguard Worker 	}
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 	*amount = s;
301*1c60b9acSAndroid Build Coastguard Worker 
302*1c60b9acSAndroid Build Coastguard Worker bail:
303*1c60b9acSAndroid Build Coastguard Worker 	if (f)
304*1c60b9acSAndroid Build Coastguard Worker 		fclose(f);
305*1c60b9acSAndroid Build Coastguard Worker 
306*1c60b9acSAndroid Build Coastguard Worker 	return n;
307*1c60b9acSAndroid Build Coastguard Worker 
308*1c60b9acSAndroid Build Coastguard Worker }
309*1c60b9acSAndroid Build Coastguard Worker #endif
310*1c60b9acSAndroid Build Coastguard Worker 
311*1c60b9acSAndroid Build Coastguard Worker /*
312*1c60b9acSAndroid Build Coastguard Worker  * filename: NULL means use buffer inbuf length inlen directly, otherwise
313*1c60b9acSAndroid Build Coastguard Worker  *           load the file "filename" into an allocated buffer.
314*1c60b9acSAndroid Build Coastguard Worker  *
315*1c60b9acSAndroid Build Coastguard Worker  * Allocates a separate DER output buffer if inbuf / inlen are the input,
316*1c60b9acSAndroid Build Coastguard Worker  * since the
317*1c60b9acSAndroid Build Coastguard Worker  *
318*1c60b9acSAndroid Build Coastguard Worker  * Contents may be PEM or DER: returns with buf pointing to DER and amount
319*1c60b9acSAndroid Build Coastguard Worker  * set to the DER length.
320*1c60b9acSAndroid Build Coastguard Worker  */
321*1c60b9acSAndroid Build Coastguard Worker 
322*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_alloc_pem_to_der_file(struct lws_context * context,const char * filename,const char * inbuf,lws_filepos_t inlen,uint8_t ** buf,lws_filepos_t * amount)323*1c60b9acSAndroid Build Coastguard Worker lws_tls_alloc_pem_to_der_file(struct lws_context *context, const char *filename,
324*1c60b9acSAndroid Build Coastguard Worker 			      const char *inbuf, lws_filepos_t inlen,
325*1c60b9acSAndroid Build Coastguard Worker 			      uint8_t **buf, lws_filepos_t *amount)
326*1c60b9acSAndroid Build Coastguard Worker {
327*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *pem = NULL, *p, *end, *opem;
328*1c60b9acSAndroid Build Coastguard Worker 	lws_filepos_t len;
329*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *q;
330*1c60b9acSAndroid Build Coastguard Worker 	int n;
331*1c60b9acSAndroid Build Coastguard Worker 
332*1c60b9acSAndroid Build Coastguard Worker 	if (filename) {
333*1c60b9acSAndroid Build Coastguard Worker 		n = alloc_file(context, filename, (uint8_t **)&pem, &len);
334*1c60b9acSAndroid Build Coastguard Worker 		if (n)
335*1c60b9acSAndroid Build Coastguard Worker 			return n;
336*1c60b9acSAndroid Build Coastguard Worker 	} else {
337*1c60b9acSAndroid Build Coastguard Worker 		pem = (uint8_t *)inbuf;
338*1c60b9acSAndroid Build Coastguard Worker 		len = inlen;
339*1c60b9acSAndroid Build Coastguard Worker 	}
340*1c60b9acSAndroid Build Coastguard Worker 
341*1c60b9acSAndroid Build Coastguard Worker 	opem = p = pem;
342*1c60b9acSAndroid Build Coastguard Worker 	end = p + len;
343*1c60b9acSAndroid Build Coastguard Worker 
344*1c60b9acSAndroid Build Coastguard Worker 	if (strncmp((char *)p, "-----", 5)) {
345*1c60b9acSAndroid Build Coastguard Worker 
346*1c60b9acSAndroid Build Coastguard Worker 		/* take it as being already DER */
347*1c60b9acSAndroid Build Coastguard Worker 
348*1c60b9acSAndroid Build Coastguard Worker 		pem = lws_malloc((size_t)inlen, "alloc_der");
349*1c60b9acSAndroid Build Coastguard Worker 		if (!pem)
350*1c60b9acSAndroid Build Coastguard Worker 			return 1;
351*1c60b9acSAndroid Build Coastguard Worker 
352*1c60b9acSAndroid Build Coastguard Worker 		memcpy(pem, inbuf, (size_t)inlen);
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 		*buf = pem;
355*1c60b9acSAndroid Build Coastguard Worker 		*amount = inlen;
356*1c60b9acSAndroid Build Coastguard Worker 
357*1c60b9acSAndroid Build Coastguard Worker 		return 0;
358*1c60b9acSAndroid Build Coastguard Worker 	}
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	/* PEM -> DER */
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 	if (!filename) {
363*1c60b9acSAndroid Build Coastguard Worker 		/* we don't know if it's in const memory... alloc the output */
364*1c60b9acSAndroid Build Coastguard Worker 		pem = lws_malloc(((size_t)inlen * 3) / 4, "alloc_der");
365*1c60b9acSAndroid Build Coastguard Worker 		if (!pem) {
366*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("a\n");
367*1c60b9acSAndroid Build Coastguard Worker 			return 1;
368*1c60b9acSAndroid Build Coastguard Worker 		}
369*1c60b9acSAndroid Build Coastguard Worker 
370*1c60b9acSAndroid Build Coastguard Worker 
371*1c60b9acSAndroid Build Coastguard Worker 	} /* else overwrite the allocated, b64 input with decoded DER */
372*1c60b9acSAndroid Build Coastguard Worker 
373*1c60b9acSAndroid Build Coastguard Worker 	/* trim the first line */
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 	p += 5;
376*1c60b9acSAndroid Build Coastguard Worker 	while (p < end && *p != '\n' && *p != '-')
377*1c60b9acSAndroid Build Coastguard Worker 		p++;
378*1c60b9acSAndroid Build Coastguard Worker 
379*1c60b9acSAndroid Build Coastguard Worker 	if (*p != '-') {
380*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("b\n");
381*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
382*1c60b9acSAndroid Build Coastguard Worker 	}
383*1c60b9acSAndroid Build Coastguard Worker 
384*1c60b9acSAndroid Build Coastguard Worker 	while (p < end && *p != '\n')
385*1c60b9acSAndroid Build Coastguard Worker 		p++;
386*1c60b9acSAndroid Build Coastguard Worker 
387*1c60b9acSAndroid Build Coastguard Worker 	if (p >= end) {
388*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("c\n");
389*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
390*1c60b9acSAndroid Build Coastguard Worker 	}
391*1c60b9acSAndroid Build Coastguard Worker 
392*1c60b9acSAndroid Build Coastguard Worker 	p++;
393*1c60b9acSAndroid Build Coastguard Worker 
394*1c60b9acSAndroid Build Coastguard Worker 	/* trim the last line */
395*1c60b9acSAndroid Build Coastguard Worker 
396*1c60b9acSAndroid Build Coastguard Worker 	q = (uint8_t *)end - 2;
397*1c60b9acSAndroid Build Coastguard Worker 
398*1c60b9acSAndroid Build Coastguard Worker 	while (q > opem && *q != '\n')
399*1c60b9acSAndroid Build Coastguard Worker 		q--;
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker 	if (*q != '\n') {
402*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("d\n");
403*1c60b9acSAndroid Build Coastguard Worker 		goto bail;
404*1c60b9acSAndroid Build Coastguard Worker 	}
405*1c60b9acSAndroid Build Coastguard Worker 
406*1c60b9acSAndroid Build Coastguard Worker 	/* we can't write into the input buffer for mem, since it may be in RO
407*1c60b9acSAndroid Build Coastguard Worker 	 * const segment
408*1c60b9acSAndroid Build Coastguard Worker 	 */
409*1c60b9acSAndroid Build Coastguard Worker 	if (filename)
410*1c60b9acSAndroid Build Coastguard Worker 		*q = '\0';
411*1c60b9acSAndroid Build Coastguard Worker 
412*1c60b9acSAndroid Build Coastguard Worker 	*amount = (unsigned int)lws_b64_decode_string_len((char *)p, lws_ptr_diff(q, p),
413*1c60b9acSAndroid Build Coastguard Worker 					    (char *)pem, (int)(long long)len);
414*1c60b9acSAndroid Build Coastguard Worker 	*buf = (uint8_t *)pem;
415*1c60b9acSAndroid Build Coastguard Worker 
416*1c60b9acSAndroid Build Coastguard Worker 	return 0;
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker bail:
419*1c60b9acSAndroid Build Coastguard Worker 	lws_free((uint8_t *)pem);
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 	return 4;
422*1c60b9acSAndroid Build Coastguard Worker }
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 
425*1c60b9acSAndroid Build Coastguard Worker #endif
426*1c60b9acSAndroid Build Coastguard Worker 
427*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) && !defined(OPTEE_DEV_KIT)
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker 
430*1c60b9acSAndroid Build Coastguard Worker static int
lws_tls_extant(const char * name)431*1c60b9acSAndroid Build Coastguard Worker lws_tls_extant(const char *name)
432*1c60b9acSAndroid Build Coastguard Worker {
433*1c60b9acSAndroid Build Coastguard Worker 	/* it exists if we can open it... */
434*1c60b9acSAndroid Build Coastguard Worker 	int fd = open(name, O_RDONLY);
435*1c60b9acSAndroid Build Coastguard Worker 	char buf[1];
436*1c60b9acSAndroid Build Coastguard Worker 	ssize_t n;
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker 	if (fd < 0)
439*1c60b9acSAndroid Build Coastguard Worker 		return 1;
440*1c60b9acSAndroid Build Coastguard Worker 
441*1c60b9acSAndroid Build Coastguard Worker 	/* and we can read at least one byte out of it */
442*1c60b9acSAndroid Build Coastguard Worker 	n = read(fd, buf, 1);
443*1c60b9acSAndroid Build Coastguard Worker 	close(fd);
444*1c60b9acSAndroid Build Coastguard Worker 
445*1c60b9acSAndroid Build Coastguard Worker 	return n != 1;
446*1c60b9acSAndroid Build Coastguard Worker }
447*1c60b9acSAndroid Build Coastguard Worker #endif
448*1c60b9acSAndroid Build Coastguard Worker /*
449*1c60b9acSAndroid Build Coastguard Worker  * Returns 0 if the filepath "name" exists and can be read from.
450*1c60b9acSAndroid Build Coastguard Worker  *
451*1c60b9acSAndroid Build Coastguard Worker  * In addition, if "name".upd exists, backup "name" to "name.old.1"
452*1c60b9acSAndroid Build Coastguard Worker  * and rename "name".upd to "name" before reporting its existence.
453*1c60b9acSAndroid Build Coastguard Worker  *
454*1c60b9acSAndroid Build Coastguard Worker  * There are four situations and three results possible:
455*1c60b9acSAndroid Build Coastguard Worker  *
456*1c60b9acSAndroid Build Coastguard Worker  * 1) LWS_TLS_EXTANT_NO: There are no certs at all (we are waiting for them to
457*1c60b9acSAndroid Build Coastguard Worker  *    be provisioned).  We also feel like this if we need privs we don't have
458*1c60b9acSAndroid Build Coastguard Worker  *    any more to look in the directory.
459*1c60b9acSAndroid Build Coastguard Worker  *
460*1c60b9acSAndroid Build Coastguard Worker  * 2) There are provisioned certs written (xxx.upd) and we still have root
461*1c60b9acSAndroid Build Coastguard Worker  *    privs... in this case we rename any existing cert to have a backup name
462*1c60b9acSAndroid Build Coastguard Worker  *    and move the upd cert into place with the correct name.  This then becomes
463*1c60b9acSAndroid Build Coastguard Worker  *    situation 4 for the caller.
464*1c60b9acSAndroid Build Coastguard Worker  *
465*1c60b9acSAndroid Build Coastguard Worker  * 3) LWS_TLS_EXTANT_ALTERNATIVE: There are provisioned certs written (xxx.upd)
466*1c60b9acSAndroid Build Coastguard Worker  *    but we no longer have the privs needed to read or rename them.  In this
467*1c60b9acSAndroid Build Coastguard Worker  *    case, indicate that the caller should use temp copies if any we do have
468*1c60b9acSAndroid Build Coastguard Worker  *    rights to access.  This is normal after we have updated the cert.
469*1c60b9acSAndroid Build Coastguard Worker  *
470*1c60b9acSAndroid Build Coastguard Worker  *    But if we dropped privs, we can't detect the provisioned xxx.upd cert +
471*1c60b9acSAndroid Build Coastguard Worker  *    key, because we can't see in the dir.  So we have to upgrade NO to
472*1c60b9acSAndroid Build Coastguard Worker  *    ALTERNATIVE when we actually have the in-memory alternative.
473*1c60b9acSAndroid Build Coastguard Worker  *
474*1c60b9acSAndroid Build Coastguard Worker  * 4) LWS_TLS_EXTANT_YES: The certs are present with the correct name and we
475*1c60b9acSAndroid Build Coastguard Worker  *    have the rights to read them.
476*1c60b9acSAndroid Build Coastguard Worker  */
477*1c60b9acSAndroid Build Coastguard Worker 
478*1c60b9acSAndroid Build Coastguard Worker enum lws_tls_extant
lws_tls_use_any_upgrade_check_extant(const char * name)479*1c60b9acSAndroid Build Coastguard Worker lws_tls_use_any_upgrade_check_extant(const char *name)
480*1c60b9acSAndroid Build Coastguard Worker {
481*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_OPTEE) && !defined(LWS_AMAZON_RTOS)
482*1c60b9acSAndroid Build Coastguard Worker 
483*1c60b9acSAndroid Build Coastguard Worker 	int n;
484*1c60b9acSAndroid Build Coastguard Worker 
485*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_PLAT_FREERTOS)
486*1c60b9acSAndroid Build Coastguard Worker 	char buf[256];
487*1c60b9acSAndroid Build Coastguard Worker 
488*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
489*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_tls_extant(buf)) {
490*1c60b9acSAndroid Build Coastguard Worker 		/* ah there is an updated file... how about the desired file? */
491*1c60b9acSAndroid Build Coastguard Worker 		if (!lws_tls_extant(name)) {
492*1c60b9acSAndroid Build Coastguard Worker 			/* rename the desired file */
493*1c60b9acSAndroid Build Coastguard Worker 			for (n = 0; n < 50; n++) {
494*1c60b9acSAndroid Build Coastguard Worker 				lws_snprintf(buf, sizeof(buf) - 1,
495*1c60b9acSAndroid Build Coastguard Worker 					     "%s.old.%d", name, n);
496*1c60b9acSAndroid Build Coastguard Worker 				if (!rename(name, buf))
497*1c60b9acSAndroid Build Coastguard Worker 					break;
498*1c60b9acSAndroid Build Coastguard Worker 			}
499*1c60b9acSAndroid Build Coastguard Worker 			if (n == 50) {
500*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("unable to rename %s\n", name);
501*1c60b9acSAndroid Build Coastguard Worker 
502*1c60b9acSAndroid Build Coastguard Worker 				return LWS_TLS_EXTANT_ALTERNATIVE;
503*1c60b9acSAndroid Build Coastguard Worker 			}
504*1c60b9acSAndroid Build Coastguard Worker 			lws_snprintf(buf, sizeof(buf) - 1, "%s.upd", name);
505*1c60b9acSAndroid Build Coastguard Worker 		}
506*1c60b9acSAndroid Build Coastguard Worker 		/* desired file is out of the way, rename the updated file */
507*1c60b9acSAndroid Build Coastguard Worker 		if (rename(buf, name)) {
508*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("unable to rename %s to %s\n", buf, name);
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 			return LWS_TLS_EXTANT_ALTERNATIVE;
511*1c60b9acSAndroid Build Coastguard Worker 		}
512*1c60b9acSAndroid Build Coastguard Worker 	}
513*1c60b9acSAndroid Build Coastguard Worker 
514*1c60b9acSAndroid Build Coastguard Worker 	if (lws_tls_extant(name))
515*1c60b9acSAndroid Build Coastguard Worker 		return LWS_TLS_EXTANT_NO;
516*1c60b9acSAndroid Build Coastguard Worker #else
517*1c60b9acSAndroid Build Coastguard Worker 	nvs_handle nvh;
518*1c60b9acSAndroid Build Coastguard Worker 	size_t s = 8192;
519*1c60b9acSAndroid Build Coastguard Worker 
520*1c60b9acSAndroid Build Coastguard Worker 	if (nvs_open("lws-station", NVS_READWRITE, &nvh)) {
521*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: can't open nvs\n", __func__);
522*1c60b9acSAndroid Build Coastguard Worker 		return LWS_TLS_EXTANT_NO;
523*1c60b9acSAndroid Build Coastguard Worker 	}
524*1c60b9acSAndroid Build Coastguard Worker 
525*1c60b9acSAndroid Build Coastguard Worker 	n = nvs_get_blob(nvh, name, NULL, &s);
526*1c60b9acSAndroid Build Coastguard Worker 	nvs_close(nvh);
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker 	if (n)
529*1c60b9acSAndroid Build Coastguard Worker 		return LWS_TLS_EXTANT_NO;
530*1c60b9acSAndroid Build Coastguard Worker #endif
531*1c60b9acSAndroid Build Coastguard Worker #endif
532*1c60b9acSAndroid Build Coastguard Worker 	return LWS_TLS_EXTANT_YES;
533*1c60b9acSAndroid Build Coastguard Worker }
534