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