TLS ALPN Proposal

Simone Bordet simone.bordet at gmail.com
Fri May 22 16:12:56 UTC 2015


Hi,

On Fri, May 22, 2015 at 2:55 AM, Bradford Wetmore
<bradford.wetmore at oracle.com> wrote:
> This is a fork of the previous thread:
>
>     Subject:  TLS Handshake Message Proposal
>               (Was: Re: JEP 244: TLS Application-Layer Protocol
>               Negotiation Extension)
>
> I broke this thread off to keep this proposal discussion together, but if
> you're interested in the history, please see the previous thread.
>
> This approach combines different suggestions from security-dev in a new way,
> and simplifies the ALPN selection process quite a bit.  I think it addresses
> most of the concerns about selection that were raised.
>
> This approach can be completely separated from the Handshake mechanism I
> discussed in the previous message, so I'm thinking of this approach for JDK
> 9 and targeting the more general handshake approach for JDK 10.
>
> Here's the summary of API additions:
>
>
> SSLParameters:
> --------------
> Client-side:  gets/sets the list of protocol names to send.
> Server-side:  gets/sets a ApplicationProtocolSelector which is a
>               user-defined callback mechanism.
>
> ApplicationProtocolSelector:
> ----------------------------
> Server-side:  callback methods for SSLSocket/SSLEngine which
>               are provided with handshake information for making
>               the selection
>
> ExtendedSSLSession:
> -------------------
> gets the negotiated protocol String

If I understand correctly, SSLParameters will have methods that can
only be used by one side of the TLS protocol (e.g. client or server,
but not both).
It's already like this for other things (e.g. SNI) so it will work,
but I had hoped for some kind of reworking in this area too, but I'm
digressing.

> /*
>  * A callback class on the server side that is responsible for
>  * choosing which Application Protocol should be used in a SSL/TLS
>  * connection.
>  */
> public abstract class ApplicationProtocolSelector {
>
>     /*
>      * SSLSocket callback to choose which Application Protocol value
>      * to return to a SSL/TLS client
>      *
>      * @param sslSocket the SSLSocket for this connection
>      * @param protocols the list of protocols advertised by the client
>      * @param protocolVersion the negotiated protocol version
>      * @param ciphersuite the negotiated ciphersuite
>      * @return a non-empty protocol String to send to the client,
>      *     or null if no protocol value (i.e. extension) should be sent.
>      * @throws SSLProtocolException if the connection should be aborted
>      *     because the the server supports none of the protocols that
>      *     the client advertised.
>      */
>     public String select(SSLSocket sslSocket, String[] protocols,
>             String protocolVersion, String ciphersuite)
>             throws SSLProtocolException;

We are currently getting the protocolVersion and the cipherSuite via:

[sslSocket|sslEngine].getHandshakeSession().get[Protocol|CipherSuite]()

If this is correct, perhaps there is no need to pass those 2
parameters to select() ?

I would suggest that if SSLParameters.setApplicationProtocols() takes
a List<String>, then also select() should take a List<String>, rather
than a String[].
Since it's the server picking the protocols, would be handy to have
the client protocols in a List<String> in order to call contains(),
etc. on it.

I would suggest to throw SSLException rather than the too specific
SSLProtocolException (which may also be misleading, since its javadoc
hints at a "flaw in one of the protocol implementations", while in
this case it is just a failure to negotiate an *application* protocol
- perfectly fine from the point of view of the TLS protocol).

Would be great if we could make this class a FunctionalInterface, but
I guess it's not easy due to lack of commonality between SSLSocket and
SSLEngine.
Unless there is a way to abstract something out of those 2 :)

> public class ExtendedSSLSession implements SSLSession {
>
>       ...deleted...
>
>       /**
>        * Gets the application protocol negotiated for this connection.
>        *
>        * @returns the application protocol name or null if none was
>        *     negotiated.
>        */
>       public String getApplicationProtocol() { };
> }

How would this case be covered:

* client sends protocol list "foo","bar"
* server sends back "bax".
* client has to decide what to do.

The only chance to call ExtendedSSLSession.getApplicationProtocol()
would be *after* the handshake is completed, right ?
Do you plan to hardcode the abort of the handshake with an alert_120,
or give the application a chance (just asking) ?

> There was also some internal discussion about whether the values should be
> Strings or byte arrays.  The ALPN RFC only discusses bytes, and a
> String.toBytes("US-ASCII") would limit the API to ASCII strings.
>
> Lastly, we could also add some convenience values for well-known values.
> e.g.:
>
>     public static final AP_HTTP_1.1 = "http/1.1";
>
> or in byte form:
>
>     public static final AP_H2 = "h2".getBytes(""US-ASCII");
>
> I refrained from including SPDY/*, since they are on their way out now, and
> NAT/STUN since there hasn't been any call for it so far.

I agree that only http/1.1 and h2 deserve a constant.

-- 
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz


More information about the security-dev mailing list