private-octopus / picoquic

Minimal implementation of the QUIC protocol
MIT License
540 stars 159 forks source link

Allow implementations to replace picotls by mbedtls #1324

Closed huitema closed 1 month ago

huitema commented 2 years ago

In a comment on the Sample code for file transfer issue #932, @jeromelau1984 wrote: can "openssl + picotls" be replaced with "mbedtls"? Whether the draft or RFC allows this. Separating this comment into its own issue, since it is not directly related to sample code.

The short answer is yes, we could support alternative to picotls, but that pretty much means replacing the implementation in tls_api.c. The initial design had that in mind, but that was 5 years ago, and since then there are probably dependencies.

Replacing openssl should be easier. Picotls has a modular architecture: a common layer implementing TLS 1.3, and a set of several cryptography providers, one of which is openssl. These providers supply implementations of common algorithms, such as AES, ChaCha20, ECC 256P, etc. There are already several different providers available, and there are picotls API allowing implementation to select their preferred provider. Picoquic already has compile flags to the cryptographic provider used in picotls. If someone implemented an mbettls provider for picotls, picoquic could use it.

There are several providers for the most common crypto algorithms, but OpenSSL is pretty much alone in providing a complete set of old algorithms, such as RSA or ECDH. Also, OpenSSL provides API for verifying certificates. This has proven hard to replace.

But first, we should assess what the goals are.

jeromelau1984 commented 2 years ago

Sorry for the late reply, I'm doing some high-priority work. The goals are to run Picoquic in iot environment, want to use smaller TLS size and reuse mbedtls, so I understand the need for a cryptographic engineer to adapt mbedtls to the tls_api.h interface. Is that right?

huitema commented 2 years ago

Yes, that would be the logical step.

Ideally, we would want that to be a run time dependency: represent the TLS API by a function table, and have examples using Picotls or Mbedtls. Then import mbedtls as an optional component in cmake, and have the application chose one or the other at run time. Also, we would need to make sure that at least some of the tests run with mbedtls loaded instead of picotls.

If we want to support IOT, we may also want to work at general size reduction, such as making some components optional, not linking them in the binary if they are not used, etc. But that would be a separate PR.

jeromelau1984 commented 2 years ago

image As shown in figure, do we need to refer to "picotls/include/ openssl.h" to add "mbedtls.h" to picotls project, define ptls_xxx_algorithm_t, link mbedtls.a or mbedtls.so and implement algorithm functions that do not exist as required.

If the above solution is correct, then we need to confirm the minimum set of algorithm functions that mbedtls can support and complete the others.

We can reduce the size of the encryption and decryption libraries first, and then optimizing other compilation options.

huitema commented 2 years ago

Yes, probably something like that. But we may want to look at the list of priorities first. There are a bunch of different ones:

1) Reduce the size of the binary. That would mean examining the object files linked in a binary, making some of them optional, and providing alternative for the ones deemed too big.

2) Reduce the memory footprint when running. We did that exercise already once, see issue #1189.

3) Provide encryption functions adapted for the ARM/IOT architecture.

4) Remove the dependency on OpenSSL.

5) Remove the dependency to PicoTLS.

Picotls itself is was specifically designed to be very compact. The architecture is a main component implementing TLS 1.3, then a plug in architecture with access to different libraries: mini crypto that has bare bone implementation of algorithms (sometimes slow), fusion for implementation of AES optimised for performance, open SSL for access to a large range of functions. Applications can select the algorithms that they want. For example, applications could be compiled with OpenSSL, and just rely on the minicrypto library.

If our goal is strictly on code size and dependencies, then the simplest solution would be to add an "mbedtls" module to picotls, providing functions like ptls_mbedtls_aes128gcm, then updating the code to have a compile option that defines extern dependencies to these functions, and then refer to these functions in the tables of supported algorithms. That would be a great first step, but that implies adding a glue component for mbedtls in the picotls project. I actually did something similar a couple years ago, providing an API for using native crypto library functions in Windows, that's not too hard.

Of course, it would also be possible to add that mbedtls glue component directly in picoquic. As long as you provide API that implement the abstract interfaces like ptls_cipher_algorithm_t, then the library can reside in either picotls or picoquic. I think your work will have a greater impact if you do it inside picotls.

Providing alternative implementation of cryptographic functions will be considerably simpler than entirely removing the dependency on picotls.

huitema commented 1 year ago

@jeromelau1984 I am coming back to this issue -- it would indeed be interesting to support MbedTLS, or at least the cryptographic functions in that library. What would be a good platform to test that support?

huitema commented 2 months ago

@jeromelau1984 The support for MbedTLS is being finalized in PR #1689. Please review it if you have time.