warmcat / libwebsockets

canonical libwebsockets.org networking library
https://libwebsockets.org
Other
4.78k stars 1.49k forks source link

mbedTLS support #472

Closed dosvald closed 7 years ago

dosvald commented 8 years ago

Hi,

is it possible that libwebsockets will support the mbedTLS (ex PolarSSL) SSL/TLS library for secure websockets?

I can see on the libwebsockets homepage that mbed platform / OS is one of supported ones. There is a version of the mbedTLS library for that platform, as well as other standard systems. Support for mbedTLS's API would mean greater support for not only embedded (mbed) OS, but it would be a global enhancement for libwebsockets in my opinion.

lws-team commented 8 years ago

It's possible, mbed3 support has stopped where it is though for a few reasons. It took a lot of time and debugging with the mbed guys before their lwip port was stable enough to run lws at all. And even after that, last time I tried it a few weeks ago even on K64F DHCP was busted due to mbed3 issues.

https://warmcat.com/embedded/iot/2015/11/03/mbed3-starting-libwebsockets-port.html https://github.com/ARMmbed/sockets/issues/35

There were other longrunning saga issues looking for freeze bugs on k64f after a certain number of packets. And they had problems as a project they were unable to accept patches, despite putting themselves on github. There's also problems with repeated public repo (pip style) module breakage because stuff only works with some dynamic mixture of pieces from git, their dhcp issues appear related to that. There seems no model to put external libs / modules like lws in their repo.

For those reasons and a lack of any feedback my enthusiasm for throwing more time at it waned, and I suggest you confirm by trying it that it meets your expectation as a stable os / network stack by now, even on their 'golden platform' of k64f, with lws before worrying about ssl.

If it is workable for you on k64f and you want to proceed with it, I'll be happy to work with you (or anyone else so minded) to see if ssl can be wired up.

dosvald commented 8 years ago

Thank you for detailed feedback! I thought mbed would be more enthusiastic...

However I'm not trying to use libwebsockets on mbed OS but rather then on OpenWrt - that said mbedtls is very well supported and integrated in OpenWrt. It would make a lot of sense if we could have mbedtls support on libwebsockets too rather then using other crypto libraries on this platform. This would reduce the amount of dependencies and would provide a lot of savings both in ram and flash. Also, this would make libwebsockets an even better project

lws-team commented 8 years ago

I understand. It makes sense for OpenWrt.

The mbedtls api has no relationship to existing openssl implementation though.

https://github.com/ARMmbed/mbedtls/blob/development/programs/ssl/ssl_client1.c

Basically it means

Right now I have a disruptive patch coming to implement vhosts, this works but not finished yet... it moves SSL_CTX to a new lws_vhost struct, so it affects every SSL_CTX reference. And another pending patch implements SNI to allow vhosts on ssl with correct cert selection also impacts ssl.c. These should be done in the next days.

Are you able to work on this? Because after that I can imagine doing the first three steps above and do the cmake plumbing to select ssl-mbedtls.c instead and maybe make sure it links to mbedtls right. But I have other things to work on, if you can think about taking on say convert the server part of ssl-mbedtls.c this can happen a lot quicker.

lws-team commented 8 years ago

I pushed the pending patches and did the first step mentioned above.

However when I went to look at the situation about SSL_CTX and SSL * on mbedtls, I immediately went off the rails... the ssl_client1.c sample I mentioned above uses apis like mbedtls_ssl_set_hostname(), but when I install mbedtls-devel package for Fedora

However if I look at the mbedtls github repo, his includes are down include/mbedtls

https://github.com/ARMmbed/mbedtls/tree/development/include/mbedtls

So I think just like mbed3 is something completely different from mbed2, mbedtls is incompatible actually with polarssl / "mbedtls in Fedora".

Can you take a look at OpenWrt "mbedtls" and see which side of the fence that is on?

lws-team commented 8 years ago

It looks like the Fedora package is ancient (1.3.16)

Openwrt uses a newer 2.0 version at least and his include path is the mbedtls one it seems

https://dev.openwrt.org/browser/trunk/package/libs/mbedtls/Makefile?rev=46484

dosvald commented 8 years ago

Yes, mbedtls on OpenWrt development branch (as you linked above) uses the new, changed/cleaned-up API which has mbedtls prefix and include directory, while older (1.x versions) have PolarSSL API and naming.

The PolarSSL 1.3.x version is used in OpenWrt stable release:

https://git.openwrt.org/?p=15.05/openwrt.git;a=blob;f=package/libs/polarssl/Makefile;h=dc13679#l12

The major version change mostly has only renames and signature changes. I didn't notice any significant design or functionality change.

https://tls.mbed.org/kb/how-to/upgrade-2.0

In my experience, for basic functionality with library defaults the rename is the only major change.

lws-team commented 8 years ago

Current Fedora has renamed the package "mbedtls" but its -devel package has things in /usr/include/polarssl, so it's neither fish nor fowl. Maybe CMake + preprocessor magic can hide this mess.

On the plus side I looked through the docs earlier: for all the api differences, in the end there is an ssl_ctx and ssl equivalent, so this should be workable.

lws-team commented 8 years ago

I added the cmake plumbing for "polarssl" and "mbedtls" cases, and adapted the includes. I didn't modify the actual ssl code yet, but I pushed it to get travis to check the ssl refactor.

https://github.com/warmcat/libwebsockets/commit/6d0ef2a09edf6863059c33e73c9f619d8f27033c

Unfortunately that was the easy bit, I have no real clue what the different apis want doing at the moment.

lws-team commented 8 years ago

This ended up with some polarssl (ie, Fedora compatible) stuff added for server only, but although it can build, it's not workable (need to disable HTTP2, CLIENT and enable POLARSSL to build that). Gaps are left for mbedtls api bits as well. It shouldn't break anything otherwise.

I'm planning to look at different things for the next days, if you're interested in working on that in the meanwhile I will happily push it somewhere.

lperkov commented 8 years ago

Hi! It would be great if libwebsockets supported mbedtls... Do you have maybe any ETA?

lws-team commented 8 years ago

If someone else helps me, 'quicker'.

The core stuff for polarssl is there (but not yet working...), once that works convert to mbedtls should be cut and paste and mainly api name changes.

lws-team commented 8 years ago

I pushed what I have on master.

This has polarssl preprocessor bits integrated everywhere so it can build normally with and without polarssl selected, so I don't have to keep it out of tree any more.

Only the server side bits are added (the client side builds OK but has no polarssl content), and it seems to load the ca / cert / key correctly into the vhost at lws_context_init_server_ssl(). Attempts to connect to it from Chrome go through the motions but get failed at ssl layer; it doesn't crash just something missing at lws_server_socket_service_ssl() ssl.c:408 onward it seems (set_dh_param? ecdh stuff?)

        ssl_session *ssn;
        int rc;

        wsi->ssl = lws_zalloc(sizeof(ssl_context));
        ssn = lws_zalloc(sizeof(ssl_session));

        rc = ssl_init(wsi->ssl);
        if (rc) {
            lwsl_err("ssl_init failed\n");
            goto fail;
        }

        ssl_set_endpoint(wsi->ssl, SSL_IS_SERVER);
        ssl_set_authmode(wsi->ssl, SSL_VERIFY_OPTIONAL);
        ssl_set_rng(wsi->ssl, urandom_bytes, NULL);
        ssl_set_dbg(wsi->ssl, pssl_debug, NULL);
        ssl_set_bio(wsi->ssl, net_recv, &wsi->sock, net_send, &wsi->sock);

        ssl_set_ciphersuites(wsi->ssl, ciphers);

        ssl_set_session(wsi->ssl, ssn);

        ssl_set_ca_chain(wsi->ssl, &wsi->vhost->ssl_ctx->ca,
                 NULL, NULL);

        ssl_set_own_cert_rsa(wsi->ssl,
                &wsi->vhost->ssl_ctx->certificate,
                &wsi->vhost->ssl_ctx->key);

//      ssl_set_dh_param(wsi->ssl, my_dhm_P, my_dhm_G);

        lwsl_err("%s: polarssl init done\n", __func__);
    }

To reproduce, I used Fedora "mbedtls" 1.3 (which is still Polarssl basically) and this

cmake .. -DLWS_USE_POLARSSL=1 -DLWS_POLARSSL_LIBRARIES=/usr/lib64/libmbedtls.so  -DLWS_POLARSSL_INCLUDE_DIRS=/usr/include/polarssl/

If anyone has worked with Polarssl apis before this isn't in such a bad shape to hack on now.

jayesh9977 commented 8 years ago

Hi, I am trying to build the libwebsockets for Mosquitto MQTT example, but it fails. Facing issuse while libev/libuv compilation for libwebsockets on QnX 660. could you please guide me on the same. thanks.

lws-team commented 8 years ago

@jayesh9977 Is your problem something to do with MbedTLS? Support for it is incomplete, which is why this issue is still open.

If your issue is unrelated to MbedTLS, please open a new issue (and cut and paste some errors since 'fails' is never a useful diagnosis)

dosvald commented 8 years ago

I started hacking in mbedTLS support (which entails mostly filling in the missing #ifdef LWS_USE_MBEDTLS parts i presume). I have some unusable work-in-progress. Will push somewhere when a bit more complete.

hemanth4ap commented 8 years ago

hi, i am using libwebsocket v1.5 as client and socket.io as sever , my client is closing connection after timeout but i want connection always open. how to handle that case . thanks.

lws-team commented 8 years ago

@hemanth4ap please open a new issue and we can discuss it there. My main question is who says it timed out? If lws timed it out, does he mention the timeout wait code? (Please answer on your new issue rather than here).

hemanth4ap commented 8 years ago

socket.io server will send ping timeout default 60sec to the client. if event is not there in client with in 60 sec after 60sec client is closing connection. but i want always connection in open state. is it possible?

lws-team commented 8 years ago

I dunno, is it possible you can open a new issue rather than hijack this one, which is about mbedTLS?

lws-team commented 8 years ago

@dosvald are we headed anywhere good with this?

dosvald commented 8 years ago

My attempt is here: https://github.com/sartura/libwebsockets/commits/mbedtls-impl , but I didn't get very far (and cmake is hacky probably).

lws-team commented 8 years ago

I think this basically isn't going to happen, there has been no other interest from other users / complaints that it is broken which is also a sign it won't repay the big effort to implement it. I'll remove it for v2.1, we can always add it back if the mbedtls cavalry appears.

dosvald commented 8 years ago

Ok. If some of my use cases should absolutely require mbedTLS, I will step up efforts for this

kapollo commented 8 years ago

I would say it would be a good idea to have some alternative to wolfssl in terms of embedded world.

lws-team commented 8 years ago

@kapollo... I completely agree... patches are very welcome (and not very hard to get started with, since the plumbing is all in there if you revert this https://github.com/warmcat/libwebsockets/commit/e8439168dcc93eeb0b2eda341db60a98d758bad2 )

SenthilKumarGS commented 7 years ago

Hello. Does libwebsockets v2.1-stable version include mbedTLS support? Or any work currently going on to add that support? Thanks.

lws-team commented 7 years ago

No, and no.

The one thing I personally wanted it for was ESP8266/32... on ESP32 they provide OpenSSL API emulation, for another recent task I might have used it lws + boringSSL worked well.

SenthilKumarGS commented 7 years ago

Thanks Mr. Andy.

I initially thought libwebsockets supports mbedTLS, as I could see some build flags specific to mbedTLS such as LWS_USE_MBEDTLS and USE_MBEDTLS. That's why i wanted to get a confirmation by posting a query here. It's clear to me now that mbedTLS is not supported.

Currently openSSL library is being used as a default (please correct me if i am wrong). I would like to know about the alternate libraries available as a replacement for it with full support (I mean, integrated with libwebsockets and ready to be used). Thanks.

lws-team commented 7 years ago

Yeah we tried to integrate it. But I guess we were not smart enough.

Anything that is compatible to openssl api will work with little or no fiddling. There are many choices about that like wolfssl, boringssl from google, etc.

SenthilKumarGS commented 7 years ago

Thanks. I really appreciate your immediate response.

jvijtiuk commented 7 years ago

Hi, I've started to work on mbedTLS support. Should PolarSSL still be supported? Fedora now comes with mbedTLS 2.5.1 as do most other distros.

Also, should the four points mentioned above (migrating ssl references to ssl.c, wrapping SSL_CTX) still be followed or have there been changes that could affect the addition of mbedTLS support?

lws-team commented 7 years ago

Whoa... a hero has risen... literally. Thanks a lot.

Since the comments on this issue, I have used an "openssl compatibility wrapper" in ESP32 esp-idf

https://github.com/espressif/esp-idf/tree/master/components/openssl

to get mbedtls as a working backend for ESP32 for both client and server. It might make sense to consider raiding that BSD-licensed backend and then just using the already-working ESP32 TLS support I added. This is only tested for ESP32 platform but it works well already.

PolarSSL has only gotten more deprecated since Feb AFAIK. If Fedora has explicitly mbedtls now then I am sold on letting someone else take care of PolarSSL if they care.

If you want to make a distinct backend from scratch it will make more sense to try to isolate the radically differing apis behind some abstraction... I will try to help you with testing if so. However if the esp-idf openssl wrapper works out as a path (you will need to study it and decide) then no need, since it's basically following selected openssl apis, and the ESP32 implementation proves those apis are enough.

jvijtiuk commented 7 years ago

Ok then, I will ignore PolarSSL and look into the esp-idf wrapper. Thanks for the quick response.

lws-team commented 7 years ago

Any progress / problems?

jvijtiuk commented 7 years ago

I have looked into the esp-idf wrapper. It looks usable, so I'm trying to use that as the backend. Right now im trying to think of the best way to use the mbedTLS backend code in the ssl .c files.

Define checks for mbedTLS could be added to the appropriate ifdefs that check for ESP_32 in the ssl files, however there are already lots of ifdef check combinations in the code so I'm trying to think of another solution.

Maybe the backend could be reused without using any ifdefs, by just using the already existing OpenSSL code and then writing the functions that don't exist in the mbedTLS backend to just do nothing. If that was done some of the backend would have to be changed to work as the OpenSSL code calls some different funtions compared to the ESP32 code, so it would require testing.

Do you have any suggestions or preferences regarding that?

lws-team commented 7 years ago

Define checks for mbedTLS could be added to the appropriate ifdefs that check for ESP_32 in the ssl files,

Yes, you need to make a cmake "LWS_WITH_MBEDTLS" symbol, which LWS_WITH_ESP32 forces on; it already forces on a bunch of things in cmake. Normal users with non-ESP32 platform just enable LWS_WITH_MBEDTLS at cmake and causes it to build the wrapper.

Right now, local to ESP32, there is enough code already existing that if the wrapper is also linked in, that mbedtls-backed client + server work well. It's "complete" but it's contaminated with LWS_WITH_ESP32 dependency. This pattern is already a "guaranteed win" then, it's already completely working on ESP32 with no doubts or unknowns, it just needs to be carefully adapted for general use while confirming it continues to work for ESP32 at each stage.

So it should be the only issue (at lws level anyway) is retargeting #if defined(LWS_WITH_ESP32) protected code into #if defined (LWS_WITH_MBEDTLS) protected code. And in cmake if LWS_WITH_ESP32 is coming, LWS_WITH_MBEDTLS is forced.

Because of this "already completely working" pattern the way to solve it is

Does it make sense?

jvijtiuk commented 7 years ago

Ok, that makes sense. I've already reused the CMakeLists changes from the previous try, so it should be a quick patch. Thanks for the help.

lws-team commented 7 years ago

Thanks to @jvijtiuk this is added to master. It needs -DLWS_USE_MBEDTLS=1 at cmake and optionally LWS_MBEDTLS_LIBRARIES and LWS_MBEDTLS_INCLUDE_DIRS.

It doesn't support everything that actual openssl does, but it supports all the basics for server and client out of the box now. I also updated the ESP32 related projects with the mbedtls-capable lws and confirmed they didn't get any problems.

MoYouenze commented 3 years ago

I use lebwebsockets and mbedtls to write a client to connect wss://openhw.work.weixin.qq.com/, but LWS is returned LWS_CALLBACK_WSIDESTROY in the handshake phase,The content of in is Server's cert didn't look good, (use ssl 0x1) X509 V ERR = 24: CA is not trusted.I want to know what's wrong.

lws-team commented 3 years ago

Like it says, you don't trust any CA so you cannot validate any certs.

Add a trusted ca cert if you don't have an os trust bundle like with openssl, eg

https://libwebsockets.org/git/libwebsockets/tree/minimal-examples/http-client/minimal-http-client/minimal-http-client.c#n296-302

MoYouenze commented 3 years ago

You mean if I use mbedtls, I have to give a CA certificate myself, right?

lws-team commented 3 years ago

You must show it which CA you will trust for that connection, if the server gives you a certificate signed by the CA, or signed by an intermediary whose cert is signed by the CA, lws will validate the connection.

If the server gives you a cert signed by anybody else, the connection fails.

Openssl comes with a big bundle of CA certs and accepts any of them automatically, like browsers do. With mbedtls and wolfssl you must explicitly provide the CA certs you are willing to trust.

MoYouenze commented 3 years ago

I'm very sorry that I still can't understand what you just said. I still don't understand why I need to provide a certificate by myself, and I don't know where to get the certificate, because I'm connected wss://openhw.work.weixin.qq.com/ , this address is one-way, I don't need to provide a certificate; I just tried to use the certificate provided in the example directly, but still failed

lws-team commented 3 years ago

Imagine there is an emperor and he has an imperial seal / chop. If you know what the emperor's seal looks like, you can trust things that the emperor signed / sealed, or people you meet that say they are imperial officers.

CA public cert: rough picture of the chop seal Server cert: server's ID card signed by the emperor

The server will let you see his ID card / server cert. But you can only feel it is valid if you know what the emperor's seal is supposed to look like (the trusted CA cert on the client) and you confirm it is his seal on it. Then you can trust that the certificate is valid and you talk to the right machine.

That is why you must have your own copy of the CA public cert that you trust. You must know what the seal should look like.

I just tried to use the certificate provided in the example directly, but still failed

Unless your site uses the same CA, it is supposed to fail.

The site you mention provides a certificate signed by this root CA, try that

https://cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem

MoYouenze commented 3 years ago

Thank you very much for your reply. I'll try it here.

MoYouenze commented 3 years ago

Hello, I have a new problem when using libwebsockets recently. A few minutes after connecting to the server, I will receive LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL, I did not process it, then I will receive LWS_CALLBACK_CLIENT_CLOSED, and finally LWS_CALLBACK_WSI_DESTROY.

But before receiving LWS_CALLBACK_WS_CLIENT_DROP_PROTOCOL, all operations can be performed normally. Now I don’t know why the callback function received it, and how to solve this problem

lws-team commented 3 years ago

Enable more verbose logging in lws and... look in the logs.

Build with -DCMAKE_BUILD_TYPE=DEBUG to get extra logs built in.