TLS ALPN Proposal v5

Bradford Wetmore bradford.wetmore at oracle.com
Sat Sep 19 05:15:58 UTC 2015


Hi all,

On 9/7/2015 7:18 AM, Simone Bordet wrote:
> On Mon, Sep 7, 2015 at 5:54 AM, Bradford Wetmore
> <bradford.wetmore at oracle.com> wrote:

>> In general, if the ciphersuites aren't ordered properly, that should be
>> considered a configuration error on the part of the application(s). However,
>> this dynamic ALPN selection approach still allows for appropriate ALPN
>> values to be selected for each possible ciphersuite. That is, if the suites
>> were ordered H1/H2, the ALPN value should be H1.
>>
>> For an example of such a selector, please see the new H2/H2+H1/H1
>> ApplicationProtocolSelector implementions in
>> ApplicationProtocolSelector.java, and how they are called in
>> ServerHandshaker.java.
>>
>>
>> Here is the latest:
>>
>> http://cr.openjdk.java.net/~wetmore/8051498/webrev.09
>
> Are you sure this is the latest code ?
> The relevant changes in ServerHandshaker are commented out.

Yes, sorry for not making this clear.  We've had a lot of internal 
discussions about the API and how to implement it:  the comments in the 
implementation classes (sun.security.ssl) are primarily for Vinnie who 
has been working on the implementation.  But I thought they provide some 
explanation as to how things might be implemented internally so I left 
them in the webrev.

> I have the feeling that ApplicationProtocolSelector (APS) is not
> really an application protocol selector, but a cipher suite selector.

It was *(note past tense)* primarily an application protocol selector. 
The fact that it could also influence ciphersuite selection was an 
optimization to avoid using suites known not to work with a particular 
ALPN value, but were going to be attempted anyway (say due to a server 
misconfiguration).

However, that has changed as the API has taken a different direction.

You mentioned "session resumption" in your email, which reminded me that 
ALPN values should be attached to connections (i.e. 
SSLSocket/SSLEngine), not SSLSessions.  That simplified things in 
several areas, especially in the Protocol Selector.

We no longer have an ApplicationProtocolSelector, but rather an 
interface called ApplicationProtocol.  These are concrete 
implementations of each ALPN/NPN value, and are responsible for 
examining the state of the connection so far and to return true if the 
conditions are right.   These instances are passed as 
List<ApplicationProtocols> to SSLParameters and then to 
SSLSocket/SSLEngines.  We have a similar but somewhat simpler server 
selection algorithm than what was described earlier:

     Select TLS version

     for each ciphersuite

         load ALPN query with:
             proposed TLS version + proposed ciphersuite
             SSLSocket/SSLEngine + handshaking state

         for each ALPN value
             if (ALPN.matches())
                 temporarily assign ALPN to the
                 handshaking SSLSocket/SSLEngine

         approve ciphersuite
             calls KeyManager for alias
                 (can use ALPN value above)
             checks cipher/MAC restrictions, etc
             break;

     if no errors
         assign ciphersuite to handshakeSession
         assign ALPN to SSLSocket/SSLEngine
         assign handshakeSesion as the actual Session
             to SSLSocket/SSLEngine

> APS seem to conflate cipher suite selection with application protocol
> selection: the return value of select() actually is a 2-tuple that
> means (ciphers[0], protocol) so that returning the empty string or
> null does not have any effect on protocol selection, but only on
> cipher selection.

To restate the point I think you raising, "Should the ALPN selection 
mechanism influence the TLS protocol version selection mechanism?"

We had a similar discussion internally.

Why would we want to encourage/enable the selection of downrev'd TLS 
protocol versions based on ALPN values?  If we actually support the 
higher/stronger TLS version, IMHO we should be using them.

1.  I think the stronger security benefits from the later protocols 
should always take priority over ALPN values and that we shouldn't be 
encouraging downrev'ing at all. For example, if there is a 
TLSv1.2/1.1/1.0 server, and we negotiated down to 1.0 just to support 
some ALPN value (or due to a bug in the selector), we lose GCM (v1.2) 
and the explicit IV (v1.1). ALPN values are application values, which I 
would expect to not be as security sensitive as the protocol values.

2.  The server hello's protocol version is supposed to be the lower of 
that suggested by the client in the client hello and the highest 
supported by the server.  Returning a lower value just to satisfy an 
ALPN selection would indicate to anyone listening (proxy, other 
connection from same VM?) that the higher TLS values are not supported 
on this server, which I think is incorrect. Future connections to this 
server might cache this lower protocol value and lose the stronger 
protocols.

3. I would expect that "older" ALPN values will likely still be 
supported in later versions of the TLS protocol. I would be surprised if 
something like http/1.1 would be phased out in TLSv1.4. If it were, apps 
probably shouldn't be offering it in combination with newer TLS versions 
in the first place.

 > You can for example implement APS without even looking at the
 > application protocol, just to exclude dynamically certain ciphers from
 > selection (e.g. based on performance or remote IP).
 >
> I don't understand exactly bullet 5 above. If APS chooses a cipher and
> a protocol, but this is not a valid combination for the KeyManager to
> select a certificate, what happens ? That APS is called again, right ?

Since the API has changed, I'll won't spend much time to comment 
here/there.  Yes, the ciphersuite is incremented for the next iteration.

> But what if that was the last cipher ? Then APS won't be called again.
> How can an application know that it is done trying to select a
> protocol and that the protocol it chose is actually used ?

Your question seems similar to asking if the KM can know if this is the 
last call it will get, and if it can know that the alias it selected 
might not be the final one.

When the connection is done handshaking, the app can check the values 
now attached to the SSLSocket/SSLEngine.  They can use the same 
Application Protocol object that did the selection/matches(), or do it 
by hand.

> I guess this also brings to bullet 6: how can an application verify
> that the N-tuple chosen is actually a correct one ? Is there an
> additional callback that is being invoked (that applications can
> implement) before the ServerHello is actually sent to the client ?

No, the ApplicationProtocol callback needs to return the right ALPN 
values for the conditions passed.

> A very important point that I saw in the comments is support for TLS
> session resumption - this has been asked multiple times by Jetty users
> that were using Jetty's ALPN (and we implemented it).
> Just make sure that whatever proposal enters JDK 9, session resumption
> is supported.

Yes, thanks for the reminder about this.   From RFC 7301:

    ...deleted...When session
    resumption or session tickets [RFC5077] are used, the previous
    contents of this extension are irrelevant, and only the values in the
    new handshake messages are considered.

So we had to move the ALPN values from session to SSLSocket/SSLEngine.

> My preference would go to the previous proposal (akin to Jetty - I
> know I am biased)

Yes, I guessed as much!  ;)

 > where protocol selection was happening in isolation
> *after* cipher selection.
> It is much simpler, and has the only drawback of not allowing
> certificate selection based on application protocol (for which we
> never had request from the community).

Understood.  But I remain concerned about that point and 
future/undefined ALPN values.


Here is the new webrev:

     http://cr.openjdk.java.net/~wetmore/8051498/webrev.12/

Unless there are major objections, we need to get ALPN into JDK very 
soon to make JDK 9.  We can still tweak the APIs if something is found 
later.

Major changes:

1.  ApplicationProtocols interface + H2 + HTTP/1.1 impls

Both client/server call SSLParameters.setApplicationProtocols(List<>) to 
set their preferences.

The matches method can be used for:

.  During server handshaking to determine an acceptable ALPN value.

.  potentially during client preparation to eliminate known bad 
ciphersuites/protocols combos.  If you are going to only request TLSv1.1 
and earlier, you can disable H2 because it won't match.

In this second case, you may not have a SSLSocket/SSLEngine yet, but you 
still want to do the checks based on ciphersuite/protocol, so the second 
parameters can be null.

2.  ApplicationProtocolSelector gone.

3.  SSLParameters AP_HTTP_1_1/AP_H2 effectively moved to 
ApplicationProtocol.  Selection logic added to ApplicationProtocol.

4.  Moved ALPN values from SSLSession to SSLSocket/SSLSEngine.  Added a 
"handshaking in progress" variant.

5.  SSLSession.getPeerApplicationProtocols() and 
getHandshakeCipherSuiteList() are gone.  These are all handled internally.

Thanks,

Brad





More information about the net-dev mailing list