diff --git a/cmake/lws_config.h.in b/cmake/lws_config.h.in index a7fcfca91..d0f81b9e8 100644 --- a/cmake/lws_config.h.in +++ b/cmake/lws_config.h.in @@ -72,6 +72,7 @@ #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_ca_chain #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_own_cert #cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_authmode +#cmakedefine LWS_HAVE_mbedtls_x509_crt_parse_file #cmakedefine LWS_HAVE_MBEDTLS_NET_SOCKETS #cmakedefine LWS_HAVE_NEW_UV_VERSION_H #cmakedefine LWS_HAVE_OPENSSL_ECDH_H diff --git a/include/libwebsockets/lws-context-vhost.h b/include/libwebsockets/lws-context-vhost.h index ee7d57dae..f40c14ddc 100644 --- a/include/libwebsockets/lws-context-vhost.h +++ b/include/libwebsockets/lws-context-vhost.h @@ -536,6 +536,17 @@ struct lws_context_creation_info { * implementation for the one provided by provided_ssl_ctx. * Libwebsockets no longer is responsible for freeing the context * if this option is selected. */ +#else /* WITH_MBEDTLS */ + const char *mbedtls_client_preload_filepath; + /**< CONTEXT: If NULL, no effect. Otherwise it should point to a + * filepath where every created client SSL_CTX is preloaded from the + * system trust bundle. + * + * This sets a processwide variable that affects all contexts. + * + * Requires that the mbedtls provides mbedtls_x509_crt_parse_file(), + * else disabled. + */ #endif #endif diff --git a/lib/core/context.c b/lib/core/context.c index 162a1bce3..fdee4fe08 100644 --- a/lib/core/context.c +++ b/lib/core/context.c @@ -30,6 +30,10 @@ static const char *library_version = LWS_LIBRARY_VERSION; +#if defined(LWS_WITH_MBEDTLS) +extern const char *mbedtls_client_preload_filepath; +#endif + #if defined(LWS_HAVE_SYS_RESOURCE_H) /* for setrlimit */ #include @@ -811,6 +815,8 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_TLS) && defined(LWS_WITH_NETWORK) #if defined(LWS_WITH_MBEDTLS) context->tls_ops = &tls_ops_mbedtls; + + mbedtls_client_preload_filepath = info->mbedtls_client_preload_filepath; #else context->tls_ops = &tls_ops_openssl; #endif diff --git a/lib/tls/CMakeLists.txt b/lib/tls/CMakeLists.txt index 78e9dab16..6b96d7318 100644 --- a/lib/tls/CMakeLists.txt +++ b/lib/tls/CMakeLists.txt @@ -359,6 +359,7 @@ if (LWS_WITH_MBEDTLS) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE) CHECK_FUNCTION_EXISTS(mbedtls_net_init LWS_HAVE_mbedtls_net_init PARENT_SCOPE) + CHECK_FUNCTION_EXISTS(mbedtls_x509_crt_parse_file LWS_HAVE_mbedtls_x509_crt_parse_file PARENT_SCOPE) # some embedded may lack filesystem CHECK_FUNCTION_EXISTS(mbedtls_md_setup LWS_HAVE_mbedtls_md_setup PARENT_SCOPE) # not on xenial 2.2 CHECK_FUNCTION_EXISTS(mbedtls_rsa_complete LWS_HAVE_mbedtls_rsa_complete PARENT_SCOPE) # not on xenial 2.2 CHECK_FUNCTION_EXISTS(mbedtls_internal_aes_encrypt LWS_HAVE_mbedtls_internal_aes_encrypt PARENT_SCOPE) # not on xenial 2.2 diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index 8f315f75d..e1f9a7136 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -363,6 +363,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, } vh->tls.x509_client_CA = d2i_X509(NULL, buf, (long)len); free(buf); + lwsl_info("Loading client CA for verification %s\n", ca_filepath); #endif } else { diff --git a/lib/tls/mbedtls/wrapper/library/ssl_lib.c b/lib/tls/mbedtls/wrapper/library/ssl_lib.c index a3220d69a..86f7bbb8c 100644 --- a/lib/tls/mbedtls/wrapper/library/ssl_lib.c +++ b/lib/tls/mbedtls/wrapper/library/ssl_lib.c @@ -179,6 +179,8 @@ OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl) return state; } +const char *mbedtls_client_preload_filepath; + /** * @brief create a SSL context */ @@ -187,6 +189,9 @@ SSL_CTX* SSL_CTX_new(const SSL_METHOD *method) SSL_CTX *ctx; CERT *cert; X509 *client_ca; +#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file) + int n; +#endif if (!method) { SSL_DEBUG(SSL_LIB_ERROR_LEVEL, "no no_method"); @@ -217,6 +222,20 @@ SSL_CTX* SSL_CTX_new(const SSL_METHOD *method) ctx->version = method->version; +#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file) + if (mbedtls_client_preload_filepath) { + mbedtls_x509_crt **px = (mbedtls_x509_crt **)ctx->client_CA->x509_pm; + + *px = malloc(sizeof(**px)); + mbedtls_x509_crt_init(*px); + n = mbedtls_x509_crt_parse_file(*px, mbedtls_client_preload_filepath); + if (n < 0) + lwsl_err("%s: unable to load cert bundle 0x%x\n", __func__, -n); + else + lwsl_info("%s: loaded cert bundle %d\n", __func__, n); + } +#endif + return ctx; failed3: diff --git a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c index 25a8b1269..b1e6c4ac0 100644 --- a/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c +++ b/minimal-examples/secure-streams/minimal-secure-streams/minimal-secure-streams.c @@ -546,6 +546,16 @@ int main(int argc, const char **argv) LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; #endif +#if defined(LWS_WITH_MBEDTLS) + + /* uncomment to force mbedtls to load a system trust store like + * openssl does + * + * info.mbedtls_client_preload_filepath = + * "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"; + */ +#endif + /* integrate us with lws system state management when context created */ nl.name = "app";