Mbed-TLS / mbedtls

An open source, portable, easy to use, readable and flexible TLS library, and reference implementation of the PSA Cryptography API. Releases are on a varying cadence, typically around 3 - 6 months between releases.
https://www.trustedfirmware.org/projects/mbed-tls/
Other
5.25k stars 2.56k forks source link

Remove cipher.h in 4.0 #8451

Open mpg opened 11 months ago

mpg commented 11 months ago

This issue is meant as a place to discuss what we want to do with Cipher in 4.0.

There are two main options:

  1. Keep it as part of the public API until 5.0, but aim to make it a thin wrapper around PSA Crypto (in 4.0 or 4.x).
  2. Remove it from the public API in 4.0, and eventually remove it entirely (in 4.0 or 4.x).

Note: Cipher currently provides functionality similar to two PSA Crypto families: psa_cipher_xxx() and psa_aead_xxx(), plus it also wraps NIST-KW (which is not covered by PSA so far, and treated as an AEAD by Cipher). It provides both streaming and one-shot API for each family.

Note: for low-level cipher/AEAD modules (aes.h, gcm.h etc) I think the plan is to remove them from the public API, regardless of what we do with Cipher - the only exception being nist_kw.h.

Rationale for option 1 (keep)

This gives users more time to move to PSA. People who were using low-level cipher/AEAD modules need to migrate immediately, but those who were using the generic Cipher/AEAD API can migrate at a convenient time between now and 5.0.

There is no PSA alternative for NIST_KW. One is coming, but we might not have it by the time 4.0 comes out.

Work needed for option 1 (keep)

In 4.0:

In 4.0 or 4.x:

Rationale for option 2 (remove)

This leaves us with only one cipher/AEAD API to maintain, document and test. For new users, this also gives more clarity.

I'll note the current cipher.h API is not very well designed, and often not documented and tested enough. (Examples that pop to mind: can I/O buffers overlap? At one point the documentation said no but TLS did it anyway. What's the default padding mode if not explicitly selected? What are the minimum sizes of the output buffers - yes, some of them are implicit...) Which I think makes it a more attractive candidate for removal than other parts of the code.

Work needed for option 2 (remove)

In 4.0:

In 4.0 or 4.x:

Other options

gilles-peskine-arm commented 11 months ago

The general wisdom for API transitions is to have one full major version cycle where the new API is stable and the old API is present but deprecated. In Mbed TLS 3, we're at an intermediate stage where the new API is stable but old API is not deprecated.

There are features of cipher that are not provided through the PSA API, but that we want to keep in the library: XTS, NIST KW. If we remove cipher, we really need to provide them through PSA, and that's a nontrivial amount of work. We're still working on an API that would be suitable for NIST KW and I'm not convinced we'll ship that in 4.0.

There are nontrivial discrepancies between the legacy cipher API and the PSA cipher/AEAD APIs. So implementing even a useful subset of cipher on top of PSA is not easy. In addition to XTS and KW:

So I'm torn. From a user's perspective, we really should keep the cipher interface as deprecated. But it's a significant amount of work.

mpg commented 11 months ago

I think there's an other option I forgot, which may be useful in cases like this (that is, where implementing the old API as a thin wrapper around PSA is not easy): keep cipher.h public, keep its implementation mostly unchanged (don't make it a wrapper around PSA), and then just migrate internal users to PSA.

People who want to keep using the Cipher API pay a higher price in code size (since Cipher's not a wrapper around PSA, there's some duplication between its implementation and PSA's cipher/aead implementation), but people who are using PSA only are not paying that price.

For us, that's less work in that we don't have to re-implement Cipher on PSA, but OTOH that means we need to prioritize migrating internal users away from Cipher in order to improve code size - but unless I'm mistaken that's something we need to do anyway to optimize code size for people who only use PSA.

mpg commented 11 months ago

There are nontrivial discrepancies between the legacy cipher API and the PSA cipher/AEAD APIs. So implementing even a useful subset of cipher on top of PSA is not easy.

And yet, unless I'm mistaken, we've done it with setup_psa(). (Though we seem to be missing a test for reset() with the same key.) Of course the problem is that it's not a thin wrapper: there is still a lot of code in cipher.c to handle the discrepancies you mention.

mpg commented 11 months ago

Note (just for reference, I don't think it influences the decision to keep Cipher or not): currently (with USE_PSA), internal users of Cipher are:

mpg commented 11 months ago

Aw, I think I forgot a work item for "option 2 (remove)": what about uses of types from cipher.h in other APIs?

Actually, I say that's a work item for option 2, but that's something we probably still want to do with option 1 anyway.

yanesca commented 2 months ago

keep cipher.h public, keep its implementation mostly unchanged (don't make it a wrapper around PSA), and then just migrate internal users to PSA.

This would mean that we still need to maintain a parallel implementation in the lifetime of 4.x. This could be quite expensive as we probably will want to adjust the low level APIs. If we still have the old cipher module implementation (I mean as opposed to being a thin wrapper) around when we do that, we will have additional constraints and update more code.

Making cipher a thin wrapper around PSA would make this problem go away, but it is expensive and risky on its own.

I think the cleanest solution here is removal (option 2). (From the user perspective in essence this is just like any other API break since we provide a stable alternative. It might only look like a removal because the stable alternative is already present.)

mpg commented 2 months ago

The problem is the parts of cipher for which there isn't a stable alternative yet: XTS and NIST KW as Gilles pointed out.

gilles-peskine-arm commented 2 months ago

My current thinking is:

mpg commented 2 months ago
  • NIST_KW doesn't have a PSA spec yet. We keep it as a public module, with an API that takes a PSA key type rather than a cipher key type.

For reference, the two changes we need to make are:

The 2nd one is likely to require us to rework the module's implementation as well to work on top of PSA APIs, but that's desirable anyway, and in the past such transitions were found to be a reasonable amount of work.

gilles-peskine-arm commented 1 month ago

Decision: we're removing cipher.h as a public interface in TF-PSA-Crypto 1.0 (and thus Mbed TLS 4.0).

This is a minor loss of functionality (e.g. cipher names, some exotic padding modes, ...).

We'll need to adapt a few things. A detailed investigation is needed. At least:

yanesca commented 2 weeks ago

We decided to go for Option 3: keep but offer no interface stability. After the repo-split the remaining task here is to document this fact clearly.