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