Hi all,

I would like to bring up the following:

  (How) Shall the APIs for PSKs and TLS session resumption be modified in Mbed TLS 3.0?

The motivation for this question is the consolidation of PSKs, ticket-based resumption
and session-id-based resumption in TLS 1.3. Now, while there will be no TLS 1.3 support
in Mbed TLS 3.0 as it stands, I think it would be beneficial to make the API amenable
to TLS 1.3 as much as possible already now.

Finding the right API here is non-trivial, and I'll describe first how the
current API works and how TLS 1.2 and 1.3 differ, before making suggestions
on how the Mbed TLS 3 API might look like. The mail is therefore quite long,
but I hope you'll bear with me.

# Session Resumption in Mbed TLS 2.X

Recall how resumption works in Mbed TLS 2.X on the client:

1. Establish a connection as usual
2. Store established session for later re-use
   `mbedtls_ssl_session_save()` saves connection parameters relevant for
   session resumption in an instance of `mbedtls_ssl_session`.

   Optional:
   2.1: Serialize session for offline storage
   2.2: Deserialize session

3. Loading a stored session
   `mbedtls_ssl_session_load()` is called on the stored session after initialization
   and before running the handshake via `mbedtls_ssl_handshake()`.

4. Connect using stored session
   Run `mbedtls_ssl_handshake()` as usual.

To my knowledge, the following is transparent to the user:
* The means by which resumption is achieved, which can be either id- or ticket-based.
* Whether the session was resumed or not - there is a silent fallback to a full
  handshake when session resumption is rejected by the server.

On the server, ticket- and id-based resumption are configured independently as follows:
- ID-based resumption is controlled via `mbedtls_ssl_conf_session_cache()`
- Ticket-based resumption is controlled via `mbedtls_ssl_conf_session_tickets_cb()`.

# PSKs in Mbed TLS 2.X

Coming to PSKs: First, recall that, under the hood, resumed connections establish
a master secret purely on the basis of a previous master secret, without resorting to
asymmetric crypto. The same is true for PSK-based connections, and this observation is
embodied in TLS 1.3 which, as mentioned, consolidates resumption and PSKs.

In TLS 1.2, though, PSKs and session resumption are different, and consequently
Mbed TLS handles them through a separate API `mbedtls_ssl_conf_psk()`, which
takes the PSK identifier and the PSK itself.

Side-question: Should this apply to the SSL configuration or the SSL context?
               It seems to me that somebody might want to run multiple PSK-based
               connections with different PSKs, but same configuration otherwise.
               At the moment, this would require a configuration per connection.

               Maybe this decision of what belongs at the level of the config
               could be thoroughly discussed independently?

# PSKs in TLS 1.3

In TLS 1.3, all kinds of resumptions are hanlded ander the umbrella of PSKs:
The client offers PSK identities in its ClientHello, the server picks one or
leaves it, and the master secret for the connection is derived from the PSK
associated with the PSK identity.

Underlying this is some form of translation

  `PSK-Identity -> PSK`

on the server which allows to derive the PSK from the PSK identity.

How this mapping is realized is entirely implementation-specific,
but it can take at least the following forms, giving back all forms
of session resumption:

- 'PSK Identity -> PSK' via database lookup:
  This subsumes classical PSKs and ID-based resumption,
  since the data necessary to resume a session is stored
  on the server.

- 'PSK Identity -> PSK' via AEAD:
  The PSK can be encoded in the PSK identity itself by using some
  authenticated encryption of the PSK as the PSK identity, the key
  for which resides on the server.
  This subsumes Ticket-based resumption.

There are the following noteworthy differences, though:

1. In TLS 1.2, the server provides a 'PSK identity hint' and the
   client picks a particular PSK identity. In TLS 1.3, the client
   offers a _list_ of PSKs, and the server picks one or none.

2. In TLS 1.2, the server can issue only a single session ticket.
   In TLS 1.3, the server can issue as many session tickets as
   he wishes, and the client can use any of those for later
   session resumption.

This has the following consequences for the API:
1. The PSK-configuration API must allow the configuration
   of multiple PSKs on the client.
2. There must be a means to export more than one session ticket
   for later resumption.

# API considerations for Mbed TLS 3.X

## Part 1: Load/Save API

In essence, keep the flow of `mbedtls_ssl_session_load/save()`,
but make the following adjustments. Whether the target structure
remains `mbedtls_ssl_session` and how it looks like internally
isn't relevant at this point and is up to discussion.

1. It must be possible 'save' a session multiple times, which
   in TLS 1.3 amounts to exporting the tickets issued by the
   server one-by-one.

   This can be realized in a variety of ways, for example:
   - Allow calling `mbedtls_ssl_session_save()` multiple
     times, and modify its semantics from the idempotent
     nature of Mbed TLS 2.X to iterating through the available
     tickets, and returning an error when no more tickets
     are available.

     This has the benefit that it likely requires no code
     change for users migrating from Mbed TLS 2.X, since
     a change is needed only when an application stores
     a single session multiple times, which could be done
     by calling `mbedtls_ssl_session_save()` multiple times
     before, while now one would need to call it once and
     manually replicate the obtained session structure.

     On the negative side, this wastes memory for applications
     not interested in session resumption, or those that only
     need a single ticket. We don't want the server to be able
     to flood the client with arbitrarily many tickets.

   - Allow registering a callback that's triggered whenever
     a new ticket arrives.

     The drawback of this is that it is larger deviation
     from the Mbed TLS 2.X API. On the positive side, applications
     that don't need tickets, or only need a limited number of
     such, can simply drop further tickets and thereby prevent
     allocating RAM for them.

2. It must be possible to 'load' multiple sessions, meaning
   that the client should offer any of them to the server for
   resumption.

## Part 2: Consolidation with PSK

Make it possible to setup an `mbedtls_ssl_session` (or whatever
it will be called) structure manually from an externally PSK
provisioned PSK, and allow loading this session for resumption
as above, via one of potentially many calls to `mbedtls_ssl_session_load()`.

There are multiple variants to this, for example:

1. Make `mbedtls_ssl_session` transparent so users can build
   it manually by filling the respective fields.

2. Provide a helper API to build a session from a PSK.

The old API `mbedtls_ssl_conf_psk()` can then be _derived_ from
this for convenience, building a session from the provided PSK
and loading it, in a single API.


Before going into further details and making the mail even
longer: What do you think of this approach? Do you see
alternatives?

Best,
Hanno
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.