I spoke with Viktor this afternoon about various scenarios being discussed on 
this thread. Going through the different use cases was very helpful in 
elucidating what functionality is appropriate.

The use cases we discussed are as follows. A and B are about multiple ticket 
requests. C and D are about ticket reuse. E is about both.

A. Multiple Tickets: Client with concurrent connections
In this scenario, a client may want to, from one initial TLS session, retrieve 
tickets for a pool of future connections. For this example, say this is four 
connections in a pool. On the initial connection, the client requests four 
tickets. It then can create four more connections, each with a unique ticket. 
From then on, each of those connections only requests a single ticket more, so 
as to get a ticket to replace the one they consumed. This allows a 
constant-sized pool of connections, where each connection gets to use tickets 
to resume.

If the server rejects a ticket due to deleting the session, the client can 
either continue to ask for one new ticket for each connection in the pool, or 
recognize that the tickets are no longer valid, and thus ask for a new batch 
(say, four new tickets) on the next handshake.

B. Multiple Tickets: Client with connection racing
For a client that wants a single connection, but may race connection 
establishment across address families (classic Happy Eyeballs) and interfaces 
(as in a mobile device case), the client may request a handful of tickets up 
front to allow connection racing. When racing, the client may consume, via 
connection attempts, more than one ticket to get one successful connection. For 
example, a client make use a ticket on a connection attempt over Wi-Fi, but 
then try LTE if Wi-Fi is stalling, and thus consume two tickets but only 
completes one connection. So, whenever a client knows it has consumed more 
tickets, it should try to repopulate the tickets. Note that it only knows how 
many it consumed *after* one is established, so it shouldn’t run its ticket 
collection dry on every connection attempt. Rather, it would probably make most 
sense to have enough tickets for two connection establishment attempts, such 
that any time many are consumed, the following handshake has the opportunity to 
ask for more.

If the server rejects a ticket due to deleting the session, all raced attempts 
for establishment will likely fail to resume together. Just like the case in 
which a client consumes many tickets due to racing, the client can only change 
the number of tickets it asks for on the *subsequent* handshake.

C. Single Ticket Reuse: Clients with trusted connection to the server, all/most 
clients reuse
If, in a controlled environment, a deployment wants to reuse tickets for 
resumption, the server can choose to allow that, and clients can choose to 
support that. If each client only needs a single ticket (since it can reuse its 
tickets), it doesn’t need to signal about multiple tickets. The one case in 
which it does need a new ticket is if the server deletes the session.

If the server knows that the majority of its clients reuse tickets, it can 
choose to simply give out a ticket only on the first handshake for a given 
client, or when a session has been deleted. For this case, no signaling should 
be needed.

D. Single Ticket Reuse: Clients wants to reuse (and server supports), most 
other clients do not reuse
As a variation, a server that supports ticket reuse in a situation when most of 
its clients do not support ticket reuse cannot simply only hand out tickets 
upon initial handshake, since most clients would then stop resuming. Instead, 
it would prefer to, by default, hand out a new ticket. For clients that *did* 
support reuse, it would be useful to have a signal. This signal is effectively 
a boolean to indicate that the client is happy with the tickets it currently 
has, and will reuse them unless the server gives out new tickets.

E. Multiple Ticket Reuse: Client want separate tickets for concurrent 
connections, that are later reused
Viktor described a case in which a client is split across multiple processes, 
so could be convenient to have independent tickets that are all retrieved from 
an initial connection that requested multiple handshakes, but the individual 
processes would want to treat those tickets as reusable until the server 
deleted the session. This case would want to both be able to request multiple 
tickets, and signal that reuse is possible.

=========

The questions I think that are most relevant are, based on our discussion:

How many distinct pieces of information are there that could be communicated 
from client to server?
Are any of these pieces fundamentally entangled, or should they be communicated 
separately? Is any capability lost by allowing them to be communicated 
separately?

To answer question 1, there are a few possible pieces of information that the 
client can send:
First is the item in the current draft, the Integer number of tickets that a 
client would like to receive from the server, based on the client’s current 
knowledge (how many tickets it already has, and if it is a new handshake or a 
resumption). This shows up in cases (A), (B), and (E).
Next is the Boolean value that indicates that a client intends to reuse the 
ticket(s) it already has, as a request to the server to only send tickets if 
the old one won’t work. This is what Viktor originally proposed to use as a 
sentinel value in the Integer space. This shows up in cases (C), (D), and (E).
A third possible item is a case that was brought up in our discussion: the 
Integer number of tickets that a client would like to receive if the current 
resumption attempt fails. The idea here is that a client in case (A) would be 
happy to only receive one ticket if the session is still valid, but would 
possibly want an entirely new batch (such as 4) if the resumption fails, so it 
can restock its ticket pool. This is certainly an interesting case, and one 
that I do consider to be in scope for the document, but I do have concerns that 
it does not apply well to all cases. For example, in scenario (B), the client 
is racing multiple connection attempts. If two or more raced attempts do hit 
the server at the same time, and the session state has been deleted, having all 
of them start to request more tickets than they would otherwise may end up 
requesting too many. Since the cases like (B) do often need to adjust their 
requests on subsequent handshakes, it seems to me that it is simpler to have 
only one value, and err on the side of requesting too few tickets on occasion 
instead of requesting some exponential amount. However, if people have 
particular opinions on this, I’d like to hear them!

So, to sum up, there are two possible Integer values to send, and one possible 
Boolean value to send.

To answer question 2, I’d point to the example use cases to conclude that, at 
the very least, the Integer number of tickets, and Boolean client intent to 
reuse tickets, are indeed separate pieces of information. Cases (A) and (B) 
only are concerned with the number of tickets. Cases (C) and (D) are only 
concerned with signaling ticket reuse. Case (E) could take advantage of both.

If we consider that these two pieces of information are independent, and can be 
used either separately or together, we can evaluate the possible approaches:
The initial proposal to carve out a sentinel value from the Integer request 
count space to signal the reuse Boolean. This approach has the downsides of not 
allowing the values to be communicated together, as well as requires that any 
implementation that supports one value must also write logic to support the 
other. As we see above, many of the use cases only need one.
The ticket_request struct could contain two separate values, an Integer and a 
Boolean. In this case, the values can be communicated alongside on another, 
which is good. It does still require handling both values in an implementation 
that only uses one.
Use the ticket_request extension for the Integer, and create a new 
prefer_ticket_reuse extension for the Boolean. This allows flexibility of 
communication, and also allows the semantics of this new extension to be 
defined, and to potentially have server response (which the ticket_request 
extension doesn’t have).

Viktor expressed two concerns with the separation proposed in approach 3:

First, the concern that the working group wouldn’t work on any more extensions 
around tickets. I hope that this would not be the case! Any valid use case that 
the working group sees fit to work on should be open to be worked on, and it is 
not the intent of the ticket request draft to preclude any future extensions 
that interact with tickets in other ways, such as specifying reuse policies.

Second, the concern that server processing logic would be too complex if these 
values weren’t combined. This I do want to dig into a bit.
From the server’s perspective, there should be three possibilities: the client 
uses only the ticket_request extension, the client uses only the 
prefer_ticket_reuse extension, or the client uses both the ticket_request and 
prefer_ticket_reuse extensions.
If the server supports both extensions, it should wait to process all client 
extensions before deciding how many tickets to send back. If the 
prefer_ticket_reuse extension is present, it would choose to not generate any 
new tickets unless session state was explicitly deleted; in that case, it would 
send tickets with a count hinted by ticket_request. My impression is that this 
does not actually constitute any more complexity in server implementation than 
if the values were present in a single extension, since the generation of 
tickets should wait until the server has finished the handshake anyway. The 
difference in implementation is only in the parsing, not in the processing.

=========

Based on this analysis, I’d recommend the following:
The proposal for hinting ticket reuse should be written up as a new draft 
proposing an extension, with discussion on use cases around ticket reuse. The 
reuse discussion can continue around that document.
Consider adding text to draft-ietf-tls-ticketrequests to explain the fact that 
when racing connections, the client won’t necessarily know the number of 
tickets it will “consume”, so it should either have enough tickets for two 
subsequent handshake resumptions; or else use fewer tickets but potentially run 
out.
Thanks,
Tommy

> On Feb 2, 2020, at 11:05 AM, Tommy Pauly <tpauly=40apple....@dmarc.ietf.org> 
> wrote:
> 
> 
> 
>> On Feb 2, 2020, at 9:53 AM, Viktor Dukhovni <ietf-d...@dukhovni.org> wrote:
>> 
>> On Sun, Feb 02, 2020 at 06:42:56AM -0800, Tommy Pauly wrote:
>> 
>>> If you did need a sentinel to indicate that you wanted to try to reuse
>>> a ticket (which you can always try if you want), it would make more
>>> sense to just make that sentinel be 255, etc, rather than creating two
>>> sentinels.
>> 
>> Sure, if you want to swap my 0 <-> 255, that'd be fine by me, then
>> 0--254 are "natural", and 255 means "only as needed".  If that's what it
>> takes to reach a compromise, I'm on board.
>> 
>>> The ticket reuse signaling that is proposed really is orthogonal to the 
>>> *count* of tickets.
>> 
>> Except that it really isn't.  Reuse means: 0 tickets or 1 ticket when
>> the one presented is or soon will become unusable.  There's no way to
>> decouple that from the ticket count.
> 
> I don’t see why one should limit the number of tickets that can be requested 
> to only 1 in a case in which a client wants ticket reuse, since the entire 
> point of this extension message is to allow requesting multiple. I understand 
> that there may be some scenarios in which a client requests multiple on the 
> initial handshake, and then wants only one more after that, but that’s not 
> necessarily the case.
> 
> For example, I connect once, and request 4 tickets so I can do happy eyeballs 
> attempts (one for v4 and v6 on each Wi-Fi and Cell, say). When I try to 
> connect later, I end up using all four of those tickets on attempts, but only 
> one succeeds. Now I want 4 more, but only have one connection. If you wanted 
> to have your ticket reuse signaling in this case, you’d want to express 
> “either give me 4 new tickets, or let me know I can reuse the previous four”, 
> in which case overloading values in the number of tickets is indeed reducing 
> the expressivity of the mechanism.
> 
> Tommy
> 
>> 
>> 
>> -- 
>>   Viktor.
>> 
>> _______________________________________________
>> TLS mailing list
>> TLS@ietf.org <mailto:TLS@ietf.org>
>> https://www.ietf.org/mailman/listinfo/tls 
>> <https://www.ietf.org/mailman/listinfo/tls>
> 
> _______________________________________________
> TLS mailing list
> TLS@ietf.org <mailto:TLS@ietf.org>
> https://www.ietf.org/mailman/listinfo/tls 
> <https://www.ietf.org/mailman/listinfo/tls>
_______________________________________________
TLS mailing list
TLS@ietf.org
https://www.ietf.org/mailman/listinfo/tls

Reply via email to