Skip to content

Adding wolfSSL support as ngtcp2 crypto library and examples. #505

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

Merged
merged 1 commit into from
Aug 12, 2022

Conversation

icing
Copy link
Contributor

@icing icing commented Aug 10, 2022

QUIC support has been added to wolfSSL (commit fa979230050dde47f6ac084c6f3b232a5e729eb5)
and ngtcp2 bindings are done as a separate crypto library.

wolfssl has been added as option to configure.

wolfssl based example client/server are build when configured
and have been verified to work against google/cloudflare/fastly
servers.

icing pushed a commit to icing/curl that referenced this pull request Aug 10, 2022
…32a5e729eb5).

- based on ngtcp2 PR ngtcp2/ngtcp2#505
- configure adapted to build against ngtcp2 wolfssl crypto lib
- quic code added for creation of WOLFSSL* instances
@tatsuhiro-t
Copy link
Member

It looks like root CMakeList.txt lacks wolfSSL detection.

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

It looks like root CMakeList.txt lacks wolfSSL detection.

Me and cmake are not really on good terms. I'd rather learn Japanese!

But let me give this a try...

@tatsuhiro-t
Copy link
Member

wolfSSL provides pkgconifg file, so it is relatively easy to deal with.
For example, look at the gnutls detection code:

  • ngtcp2/CMakeLists.txt

    Lines 89 to 91 in dfcdcc8

    if(ENABLE_GNUTLS)
    find_package(GnuTLS 3.7.2)
    endif()
  • ngtcp2/CMakeLists.txt

    Lines 162 to 171 in dfcdcc8

    # GnuTLS (required for libngtcp2_crypto_gnutls)
    if(ENABLE_GNUTLS AND GNUTLS_FOUND)
    set(GNUTLS_INCLUDE_DIRS ${GNUTLS_INCLUDE_DIR})
    set(HAVE_GNUTLS TRUE)
    set(HAVE_CRYPTO TRUE)
    else()
    set(HAVE_GNUTLS FALSE)
    set(GNUTLS_INCLUDE_DIRS "")
    set(GNUTLS_LIBRARIES "")
    endif()

If you have hard time or no time to deal with cmake, then leave it to me.

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

Always willing to learn. I have installed all my quic related libs in /opt/quic. How would I invoke cmake to search there first?

@tatsuhiro-t
Copy link
Member

cmake understands PKG_CONFIG_PATH environment variable. List the custom install path in the variable. Then cmake will search them first.

@tatsuhiro-t
Copy link
Member

With the above comments, I can successfully compile the patch.

After some tries of client and server, wsslclient works regular connection (nice!). But it is unable to send 0-RTT.
wsslserver is unable to get ALPN, that is wolfSSL_ALPN_GetProtocol returns -9.

I built wolfssl with the following configure options: --enable-quic --enable-session-ticket --enable-earlydata --enable-alpn
wolfssl provides fine grained feature options, so I might miss something important.

@tatsuhiro-t
Copy link
Member

Right, --enable-all fixes ALPN issue.

@tatsuhiro-t
Copy link
Member

wsslserver has some issues on resumption.

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

wsslserver has some issues on resumption.

Manual testing or do you have some scripting?

@tatsuhiro-t
Copy link
Member

I use ngtcp2 examples/client to test resumption and 0 RTT.
Adding --session-file session.txt --tp-file tp.txt to client command-line will save session info in session.txt and quic transport parameters in tp.txt. Run the client with the same options again, which will read session info and transport parameters from the files and try to do resumption.

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

I use ngtcp2 examples/client to test resumption and 0 RTT.
Adding --session-file session.txt --tp-file tp.txt to client command-line will save session info in session.txt and quic transport parameters in tp.txt. Run the client with the same options again, which will read session info and transport parameters from the files and try to do resumption.

Thanks. Can reproduce. wsslclient can resume against wsslserver, but client fails. Hmm...

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

It looks like root CMakeList.txt lacks wolfSSL detection.

cmake is now working on my machine. please check.

@icing
Copy link
Contributor Author

icing commented Aug 10, 2022

I think I isolated the problem in wolfSSL that leads to failures in resumption with an openssl client. See wolfSSL/wolfssl#5452 for the PR that demonstrates the problem and a possible solution.

@tatsuhiro-t
Copy link
Member

It sounds like the same behavior as boringssl does.

if (SSL_in_early_data(ssl)) {

boringssl SSL_do_handshake returns 1 when it sends server finished to read early data from client. It provides SSL_in_early_data function to determine the actual TLS handshake completed or not. ngtcp2 boringssl binding uses it to decide whether keep calling SSL_do_handshake or not.

@tatsuhiro-t
Copy link
Member

cmake is now working on my machine. please check.

Thank you. cmake now works for wolfssl binding library.

@icing
Copy link
Contributor Author

icing commented Aug 11, 2022

It sounds like the same behavior as boringssl does.
...
boringssl SSL_do_handshake returns 1 when it sends server finished to read early data from client. It provides SSL_in_early_data function to determine the actual TLS handshake completed or not. ngtcp2 boringssl binding uses it to decide whether keep calling SSL_do_handshake or not.

Yes, indeed.

wolfSSL merged my addition of a wolfSSL_quic_do_handshake() that handles this situation and I pushed the necessary changes here now.

In my local testing, openssl example client resumes against wolfssl server and early data seems to work as well.

@tatsuhiro-t
Copy link
Member

Yeah, it is much better now.
Resumption works, but early data is rejected by server: Early data was rejected by server.

It seems that wolfssl server only accepts early data if wolfSSL_read_early_data is called. Inside it, it setups ssl->earlyData = expecting_early_data. QUIC does not use the function. Needs to do this somewhere.

@tatsuhiro-t
Copy link
Member

While I was playing around wolfSSL server 0RTT, it looks like it sends early_data extension even if it rejects resumption.
It also happens with the regular TLSv1.3 connection over TCP.

@icing
Copy link
Contributor Author

icing commented Aug 11, 2022

I am wrestling with it. Seems that feature could do with some more attention.

@icing
Copy link
Contributor Author

icing commented Aug 11, 2022

Ok, just created wolfSSL/wolfssl#5458 which in my tests with openssl/wolfssl based client/server examples here no longer rejects early data.

No changes necessary to this PR other than the git change id update after wolfSSL merged.

@tatsuhiro-t
Copy link
Member

Yes, the PR has been merged, and I confirmed that 0RTT now works for both wsslclient and wsslserver. Thank you very much.

The remaining issue is when wsslserver receives a session ticket which it cannot resume.
With the latest wolfssl build, I observed that QUIC handshake encryption and decryption key do not agree between client and wsslserver in this case.

@tatsuhiro-t
Copy link
Member

It is interesting that the disagreement of keys happens if session ticket has not been expired yet (you can trigger this condition by restarting server, and use the ticket that the old server issued). After some time, I guess that the ticket has been expired, now both parties agree with the keys, but server still sends early_data extension in full handshake. OpenSSL does not like this and issues TLS alert.

@tatsuhiro-t
Copy link
Member

The issue mentioned above happens with regular TLSv1.3 connection over TCP.
Steps to repro:

  1. Run wolfssl examples server: examples/server/server -0 -v 4 -d -C10000
  2. Run openssl client: openssl s_client -connect localhost:11111 -sess_out session.txt -early_data data.txt
  3. Stop openssl client (ctrl-C)
  4. Stop wolfssl examples server
  5. Start wolfssl server again with the same options.
  6. Run openssl client: openssl s_client -connect localhost:11111 -sess_out session.txt -sess_in session.txt -early_data data.txt

Now I get 140059142509952:error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac:../ssl/record/ssl3_record.c:676:

After some time, do step 5 and 6 (needs step 5 because wolfssl example server stops as a result of step 6) and I get 140609374721408:error:1421A06E:SSL routines:tls_parse_stoc_early_data:bad extension:../ssl/statem/extensions_clnt.c:1946:

It seems that these are not QUIC specific. I'm not sure how the fix impacts the QUIC stuff, but I think we can go ahead and just polish up the current PR and merge it.

@icing
Copy link
Contributor Author

icing commented Aug 12, 2022

The issue mentioned above happens with regular TLSv1.3 connection over TCP. Steps to repro:

  1. Run wolfssl examples server: examples/server/server -0 -v 4 -d -C10000
  2. Run openssl client: openssl s_client -connect localhost:11111 -sess_out session.txt -early_data data.txt
  3. Stop openssl client (ctrl-C)
  4. Stop wolfssl examples server
  5. Start wolfssl server again with the same options.
  6. Run openssl client: openssl s_client -connect localhost:11111 -sess_out session.txt -sess_in session.txt -early_data data.txt

Now I get 140059142509952:error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac:../ssl/record/ssl3_record.c:676:

After some time, do step 5 and 6 (needs step 5 because wolfssl example server stops as a result of step 6) and I get 140609374721408:error:1421A06E:SSL routines:tls_parse_stoc_early_data:bad extension:../ssl/statem/extensions_clnt.c:1946:

Nice find. I will try to reproduce and then open an Issue at wolfSSL about it.

It seems that these are not QUIC specific. I'm not sure how the fix impacts the QUIC stuff, but I think we can go ahead and just polish up the current PR and merge it.

Excellent! Many thanks for the fast testing. I'll polish based on your feedback and rebase/squash afterwards.

- adding --with-wolfssl as configure option
- adding cmake support
- adding examples/wsslclient and examples/wsslserver using
  the wolfssl ngtcp2 crypto library
@icing
Copy link
Contributor Author

icing commented Aug 12, 2022

Sorry, for having to stumble across all my leftovers.

@icing
Copy link
Contributor Author

icing commented Aug 12, 2022

Reported the resumption problem as wolfSSL/wolfssl#5463.

@tatsuhiro-t
Copy link
Member

Thank you for fixing all issues. Now LGTM.

@tatsuhiro-t tatsuhiro-t added this to the v0.8.0 milestone Aug 12, 2022
@tatsuhiro-t tatsuhiro-t merged commit f0b46cf into ngtcp2:main Aug 12, 2022
bagder pushed a commit to curl/curl that referenced this pull request Aug 14, 2022
- based on ngtcp2 PR ngtcp2/ngtcp2#505
- configure adapted to build against ngtcp2 wolfssl crypto lib
- quic code added for creation of WOLFSSL* instances

Closes #9290
@vszakats
Copy link
Contributor

vszakats commented Aug 15, 2022

Can someone confirm that the TLS-backend specific headers ngtcp2_crypto.h and ngtcp2_crypto_wolfssl.h are not copied by make install to their destination when using CMake?

UPDATE: PR opened.

vszakats added a commit to curl/curl-for-win that referenced this pull request Aug 15, 2022
It requires this ngtcp2 commit, or newer:
ngtcp2/ngtcp2@f0b46cf

There is no tagged release with it yet.

ngtcp2 doesn't seem to install two necessary headers, so we do it
manually for the time being.

Ref: ngtcp2/ngtcp2#505 (comment)
jquepi pushed a commit to jquepi/curl.1.555 that referenced this pull request Oct 24, 2022
- based on ngtcp2 PR ngtcp2/ngtcp2#505
- configure adapted to build against ngtcp2 wolfssl crypto lib
- quic code added for creation of WOLFSSL* instances

Closes #9290
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants