Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CivetWeb sample only supports HTTP, Zephyr lacks TLS support #34438

Closed
madscientist159 opened this issue Apr 20, 2021 · 20 comments
Closed

CivetWeb sample only supports HTTP, Zephyr lacks TLS support #34438

madscientist159 opened this issue Apr 20, 2021 · 20 comments
Labels
area: civetweb area: Networking Enhancement Changes/Updates/Additions to existing features

Comments

@madscientist159
Copy link

madscientist159 commented Apr 20, 2021

Is your enhancement proposal related to a problem? Please describe.
We need an encrypted method to transfer data to and from a remote Zephyr system. Plain text telnet / HTTP will not suffice.

Describe the solution you'd like
We'd like to see integration of Zephyr, CivetWeb, and mbedtls into a concise sample application.

Describe alternatives you've considered
Adding a TLS server to Zephyr. The incomplete POSIX API is a significant concern, and HTTPS is more useful for the end application.

Additional context
Upstream CivetWeb theoretically supports mbedtls as of a couple of weeks ago. We've been running the upstream CivetWeb with no problems using standard HTTP, but need SSL support at some point.

@madscientist159 madscientist159 added the Enhancement Changes/Updates/Additions to existing features label Apr 20, 2021
@jukkar
Copy link
Member

jukkar commented Apr 21, 2021

Instead of SSH, a bit more easier route might be to port Wireguard to Zephyr. Someone has ported it to lwip so it should be possible to port that one to Zephyr. https://github.com/smartalock/wireguard-lwip

@jukkar
Copy link
Member

jukkar commented Apr 21, 2021

If you only need HTTPS client support, then Zephyr already provides native HTTP client API that also support mbedtls. See include/net/http_client.h for API details. There is also a sample app in samples/net/sockets/http_client.

@madscientist159
Copy link
Author

madscientist159 commented Apr 22, 2021

@jukkar Thanks for the client hint, but we do need HTTPS server support....

See https://twitter.com/RaptorEng/status/1385175244881727491 for an example of what we have so far; HTTPS is going to be needed to get Redfish implemented securely.

@jukkar
Copy link
Member

jukkar commented Apr 23, 2021

@Nukersson did you had any plans for HTTPS support for civetweb?

@KozhinovAlexander
Copy link
Collaborator

KozhinovAlexander commented Apr 23, 2021

@Nukersson did you had any plans for HTTPS support for civetweb?

Hey @jukkar and thank you. Currently I do not have a time to merge newer Civetweb into Zephyr and provide some good https server example. I am just busy on other proprietary projects. But it may be possible for anyone else, based on my already implemented samples. I am ready to support this person.

@mglettig
Copy link

I am also interested in having HTTPS support in civetweb. Civetweb v1.14 is the latest release and also the first version that supports the mbedtls library. So I guess there is a chance to get HTTPS working when integrating the latest release v1.14 in Zephyr and setting the WITH_MBEDTLS=1 when building civetweb.

@mglettig
Copy link

mglettig commented May 6, 2021

I thought I would give it a shot and try to integrate Civetweb 1.14 and enable MBEDTLS. However I'm already struggling on how to enable mbedtls and tell civetweb to link against mbedtls. Also civetweb needs to know where the mbedtls header files are located.
I found the following section in the Makefile of civetweb:

ifdef NO_SSL CFLAGS += -DNO_SSL else ifdef WITH_MBEDTLS CFLAGS += -DUSE_MBEDTLS LIBS += -lmbedcrypto -lmbedtls -lmbedx509
See here: https://github.com/civetweb/civetweb/blob/master/Makefile#L96

So I guess I need to disable NO_SSL and enable WITH_MBEDTLS from the buildsystem. Also the compile definition USE_MBEDTLS needs to be set. How can I configure this in zephyr?
@Nukersson Can you help me here?

@KozhinovAlexander
Copy link
Collaborator

I thought I would give it a shot and try to integrate Civetweb 1.14 and enable MBEDTLS. However I'm already struggling on how to enable mbedtls and tell civetweb to link against mbedtls. Also civetweb needs to know where the mbedtls header files are located.
I found the following section in the Makefile of civetweb:

ifdef NO_SSL CFLAGS += -DNO_SSL else ifdef WITH_MBEDTLS CFLAGS += -DUSE_MBEDTLS LIBS += -lmbedcrypto -lmbedtls -lmbedx509
See here: https://github.com/civetweb/civetweb/blob/master/Makefile#L96

So I guess I need to disable NO_SSL and enable WITH_MBEDTLS from the buildsystem. Also the compile definition USE_MBEDTLS needs to be set. How can I configure this in zephyr?
@Nukersson Can you help me here?

The simples first test for you would be putting it as #define WITH_MBEDTLS just in main.cpp of http_server sample of Civetweb. Then you can see if other problem occures.

Later this defines should go into KConfig or so. I can help you with this later. Maybe just we can make a call if you really interested in providing this PR. Anyway thank you for your work.

@mglettig
Copy link

mglettig commented May 7, 2021

To get further on this topic I introduced a new KConfig parameter in modules/KConfig.civetweb called "CONFIG_USE_MBEDTLS". Then in civetweb.c I do the following:

#ifdef CONFIG_USE_MBEDTLS
#define USE_MBEDTLS
#endif

Is modules/KConfig.civetweb the right place to put this KConfig parameter?

Additionally I need to set the following configuration flags in order to make sure mbedtls is linked against the target:

CONFIG_MBEDTLS=y
CONFIG_APP_LINK_WITH_MBEDTLS=y
CONFIG_MBEDTLS_ENTROPY_ENABLED=y

Later those configuration parameters could depended on CONFIG_USE_MBEDTLS.

So far so good. But now some mbedtls functions desired by civetweb are still missing. I enable them by changing the config file as follows:

diff --git a/configs/config-tls-generic.h b/configs/config-tls-generic.h
index 06ceb02..96adea5 100644
--- a/configs/config-tls-generic.h
+++ b/configs/config-tls-generic.h
@@ -18,6 +18,8 @@
 #define MBEDTLS_PLATFORM_EXIT_ALT
 #define MBEDTLS_NO_PLATFORM_ENTROPY
 #define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_FS_IO
  
 #if defined(CONFIG_MBEDTLS_HAVE_ASM)
 #define MBEDTLS_HAVE_ASM

But setting MBEDTLS_FS_IO leads to the problem that mbedtls needs functions from POSIX_DEVICE_IO like fopen and fclose. Those functions are not available in Zephyr. Any idea on how to proceed with this problem? For me it looks like missing POSIX functions are responsible for a lot of issues with Zephyr modules.

@KozhinovAlexander
Copy link
Collaborator

Good beginning. Sure you need to implement / reimplement multiple posix functions as Civetweb were primarily developed for Linux, I believe. But anyway you can first put some "fake" functions into Civetweb examples. In my example there should be a file containing some faked posix functions. Just follow same way for the first time. You can just return default values in newly added functions.

Additional solution would be to contact Zephyr's posix Dev group. But, as I know there is not much progress currently.

@madscientist159
Copy link
Author

FWIW fopen()/fclose() drag in a bunch of file / directory structures, and we aborted that approach as it looked to be over a month of effort to get something even close to working.

The more appropriate question is, why is mbedtls expecting to do file I/O on an embedded platform without a filesystem?

@mglettig
Copy link

mglettig commented May 10, 2021

I think @madscientist159 is right. The right way to approach this issue is to avoid that civetweb uses the following functions:

Because those functions are generally not really supported on embedded systems (systems without POSIX_DEVICE_IO support). Instead the first 2 functions could be replaced by mbedtls_pk_parse_key and mbedtls_x509_crt_parse_der. Any ideas for how to replace the 3rd function?

What would be the best way to introduce those changes to civetweb so that the PR gets accepted?

@mglettig
Copy link

In the meantime I managed to find a solution for parsing the private key file and the certificate. I also managed to find a temporary solution for some issues with entropy.

Now I'm struggling with incorporating the networking stack from Zephyr. According to the mbedtls porting guide the

network module net_sockets.c that can be disabled and replaced with a separate network stack

Can anybody help me on how to do that? I guess I need to define my own implementation of mbedtls_net_send and mbedtls_net_recv that use something like zsock_sendto and zsock_recvfrom. Then register those functions with mbedtls_ssl_set_bio. But what else is needed?

Any ideas @madscientist159 or @Nukersson?

@KozhinovAlexander
Copy link
Collaborator

In the meantime I managed to find a solution for parsing the private key file and the certificate. I also managed to find a temporary solution for some issues with entropy.

Now I'm struggling with incorporating the networking stack from Zephyr. According to the mbedtls porting guide the

network module net_sockets.c that can be disabled and replaced with a separate network stack

Can anybody help me on how to do that? I guess I need to define my own implementation of mbedtls_net_send and mbedtls_net_recv that use something like zsock_sendto and zsock_recvfrom. Then register those functions with mbedtls_ssl_set_bio. But what else is needed?

Any ideas @madscientist159 or @Nukersson?

@jukkar Can you add here something?

@jukkar
Copy link
Member

jukkar commented May 11, 2021

I am not very familiar with mbedtls porting, @rlubos do you know anything about this?

@rlubos
Copy link
Contributor

rlubos commented May 12, 2021

I'm not familiar with net_sockets.c from mbedTLS, but it seems to be using posix socket API, so I wonder if any porting is needed at all (we support this in Zephyr). Perhaps some features are missing, I haven't gone deep into the code.

But if you cannot use it and need to setup mbedTLS manually, you may want to have a look at Zephyrs Secure socket implmentation as an example.

@mglettig
Copy link

mglettig commented May 21, 2021

I have a first working prototype here. My changes are no yet cleaned up and not ready for a PR but for a discussion it should be sufficient. Please have a look at the following changes: civetweb/civetweb@master...endresshauser-lp:feature/https_support

Some explanations on what I needed to change:

  • Introduction of a new KConfig value for civetweb module: CONFIG_USE_MBEDTLS
    -- Where is the right place to put this KConfig parameter? I put it in /modules/Kconfig.civetweb.
    -- This KConfig value controls the compile switch USE_MBEDTLS in civetweb.
  • Providing entropy functions. I did the same as in
    #if defined(CONFIG_ENTROPY_HAS_DRIVER)
    .
    -- Here I think we should refactor something in Zephyr to avoid code duplication.
  • Changes for certificate parsing: civetweb/civetweb@master...endresshauser-lp:feature/https_support#diff-c80125e764fb5b068dc73f832e179506a350117830cf5b871887d4f12fc54555R157
    -- For my tests I no longer read the certificate from a file but put it directly in the civetweb configuration. I think this will need to be changed by using the Zephyr specific file read functions.
  • Using mbedtls_ssl_set_bio(*ssl, sock, tls_tx, tls_rx, NULL); and implementing tls_tx and tls_rx I made the link to the Zephyr BSD sockets.

With this changes I was able to access civetweb over HTTPS.

@mglettig
Copy link

mglettig commented Jun 2, 2021

Is anybody willing to discuss my points from the last post?

@rlubos
Copy link
Contributor

rlubos commented Jun 2, 2021

A few comments from my side:

Where is the right place to put this KConfig parameter? I put it in /modules/Kconfig.civetweb.

This is a good location for module-related Kconfig entries.

Providing entropy functions. I did the same as in

Note that entropy handling in TLS sockets implmentation is a subject of change after the release. Zephyr provides its own secure RNG for some time now, and secure sockets are going to use it:
https://github.com/zephyrproject-rtos/zephyr/pull/35166/files

Here I think we should refactor something in Zephyr to avoid code duplication.

I think we could consider to add a generic mbedtls_platform_entropy_poll(), although I think it's a separate issue from the Civetweb.

Changes for certificate parsing: civetweb/civetweb@master...endresshauser-lp:feature/https_supportdiff-c80125e764fb5b068dc73f832e179506a350117830cf5b871887d4f12fc54555R157
-- For my tests I no longer read the certificate from a file but put it directly in the civetweb configuration. I think this will need to be changed by using the Zephyr specific file read functions.

I'm sorry, I'm not able to open the link. But if it's a matter of reading a certificate from a file with POSIX functions, I think we might have it already in Zephyr (I'm sorry but I'm not 100% sure - I don't have experience with Zephyr filesystems). See CONFIG_POSIX_FS and lib/posix/fs.c - it seems to provide a thin wrapper between POSIX and Zephyr APIs.

Using mbedtls_ssl_set_bio(*ssl, sock, tls_tx, tls_rx, NULL); and implementing tls_tx and tls_rx I made the link to the Zephyr BSD sockets.

It should be a good reference for a TLS implementation with mbedTLS, out of curiosity though, what was the problem with the original implementation (mbedtls_net_send/mbedtls_net_recv)? It seems to use read/write/fcntl underneath, all of which we have in Zephyr in the context of sockets.

@stephanosio stephanosio changed the title CivetWeb sample only supports HTTP, Zephyr lacks SSH support CivetWeb sample only supports HTTP, Zephyr lacks TLS support Aug 26, 2021
@gmarull
Copy link
Member

gmarull commented Aug 11, 2022

civetweb is no longer part of Zephyr, closing

@gmarull gmarull closed this as completed Aug 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: civetweb area: Networking Enhancement Changes/Updates/Additions to existing features
Projects
None yet
Development

No branches or pull requests

6 participants