Hi all,

On 9/7/2015 7:18 AM, Simone Bordet wrote:
On Mon, Sep 7, 2015 at 5:54 AM, Bradford Wetmore
<bradford.wetm...@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



Reply via email to