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