h2o / picotls

TLS 1.3 implementation in C (master supports RFC8446 as well as draft-26, -27, -28)
535 stars 140 forks source link

Ptls mbedtls #485

Closed huitema closed 10 months ago

huitema commented 1 year ago

The goal of this PR is to support MbedTLS as an alternative to OpenSSL, especially on "embedded" platforms.

The first milestone is to verify that CMake and Make work properly and produce a library picotls-mbedtls and a test program t.mbedtls when using the option "WITH_MBEDTLS=ON". The current set of supported algorithms is minimal -- mainly, aes128_gcm with sha256. MbedTLS supports a much larger range of algorithm, which will be added later.

huitema commented 1 year ago

The "mbedtls" github action could probably be integrated in the general CI/matrix... but I don't know exactly how.

kazuho commented 1 year ago

Thank you for your efforts.

I get that openssl (libcrypto) is not always the best choice, but may I ask what the problem is with using minicrypto?

I'm asking this as I fear the addition of new backends becoming a drag for picotls to evolve, even though I think it makes sense to have one backend for each purpose.

huitema commented 1 year ago

My main motivation is developer demand. I am getting requests to support MbedTLS in picoquic, mostly for Arduino-class platforms. There are perceived advantages of using MbedTLS there, mostly because it is supported by ARM and thus comes as part of the system. So, the hope is for good performance with minimal additional increase in software size.

Yes, we could make the case that minicrypto also works in these platforms, because it is portable and small. I do not know how the performance compare. To answer that, I will add the MbedTLS algorithms to "ptlsbench", run that program on target platforms such as Arduino or Raspberry Pi.

The other issue is completeness. I am not done porting, but MbedTLS does include more algorithms than minicrypto: rsa in particular, which is useful in some deployments. That might help solve the main issue with minicrypto: clients cannot verify server certificates.

I will pursue this PR at least until I can get the performance numbers. If they are no different from minicrypto, the case from adding MbedTLS support inside picotls becomes much weaker.

kazuho commented 1 year ago

@huitema Thank you for elaborating. mbedTLS being the in-house stack provided by ARM is a good argument, I think it's analogous to us having support for Microsoft Crypto API.

huitema commented 1 year ago

Here is the outpout of ptlsbench, on an M11 iMac:

provider version algorithm N L encrypt us decrypt us encrypt mbps decrypt mbps
minicrypto aes128gcm 1000 1500 1286059 1266238 9.33 9.48
minicrypto aes256gcm 1000 1500 1757690 1757558 6.83 6.83
minicrypto chacha20poly1305 1000 1500 14340 14347 836.82 836.41
openssl 3.1.0a chacha20poly1305 1000 1500 1352 1324 8875.74 9063.44
openssl 3.1.0a aes128gcm 1000 1500 307 284 39087.95 42253.52
openssl 3.1.0a aes256gcm 1000 1500 340 323 35294.12 37151.70
mbedtls aes128gcm 1000 1500 38069 36561 315.22 328.22
mbedtls aes256gcm 1000 1500 44789 43204 267.92 277.75
mbedtls chacha20poly1305 1000 1500 37130 36993 323.19 324.39

The chachapoly implementation in MbedTLS is more than 2 times slower than minicrypto, but the AES GCM implementation is 30 times faster than minicrypto. It is of course more than 100 times slower than OpenSSL. Based on AES alone, I would rather use it than minicrypto on an ARM platform if OpenSSL is not an option.

kazuho commented 1 year ago

Thank you for working on this pull request. I'll take a look pretty soon.

One question: would it be possible or make sense to define a cert verifier (like ptls_openssl_init_verify_certificate) using mbedTLS? IIRC that's one of the things that's missing in minicrypto aside from RSA.

huitema commented 1 year ago

It would indeed make sense to add a certificate verifier.

MbedTLS includes generic "message verifier" functions (https://armmbed.github.io/mbed-crypto/html/api/ops/sign.html#psa_verify_message) for verifying a message using asymmetric crypto. This is not exactly a certificate verifier, but it could be the basis for one.

Verifying a individual certificate includes parsing it using ASN.1, checking that the date is valid, verifying the signature. We have the ASN.1 step done in minicrypto. We could build a generic 'certificate verifier' that uses a list of available "message verifier" functions, one for each supported asymmetric algorithm. That list of symmetric algorithms could be imported from packages like openssl, mbedtls, minicrypto, bcrypt -- much in the same way that supported AEAD algorithms or key exchanges are provisioned into the PTLS context.

That's quite a bit of plumbing. The first step would be to define a "asymmetric cipher" template, probably with callbacks for init, sign, verify and free. We could instantiate that for ECDSA/secp256r1 in minicrypto, and then do the imports from openssl, mbedtls, etc.

I believe this "asymmetric cipher" template work should be part of a different effort. What do you think?

huitema commented 1 year ago

@kazuho I would like to merge this PR, as it provides a reasonably complete list of hash methods, ciphers, aead, cipher suites and key exchanges. In fact, it provides all the methods supported in minicrypto, and the tests verify compatibility with minicrypto.

I would like to open an issue to discuss the certificate verifier options. As mentioned above, we have to first agree on the architecture, and I would prefer doing that in a specific issue rather than in this PR. Once we have agreement, we can add declarations of signature or verification with RSA, ECDSA, EDDH.

MbedTLS provides more methods than those listed here. I only developed the minicrypto subset, because it is a good fit for TLS 1.3. It would not be very hard to add support for other methods like MD5, SHA1, SHA512, ARC4, Camelia, DES, CCM variants of AEAD, AEAD variants with shortened tags, or finite-field Diffie-Hellman. The main work will be to develop the corresponding tests. But then, supporting more methods increases the code size...