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



Specifics below.  The javadoc obviously needs work.

class SSLParameters {

    ...deleted...

    /**
     * Gets the list of application protocols that will sent by
     * the client.
     *
     * The list could be empty, in which case no protocols will be
     * sent.
     *
     * @returns a list of application protocol names.
     */
    public List<String> getApplicationProtocols() { };

    /**
     * Sets the list of application protocols that will sent by
     * the client.
     *
     * protocols could be empty, in which case no protocols will be
     * sent.
     *
     * @param protocols a list of application protocol names
     * @throws IllegalArgumentException if protocols is null.
     */
    public void setApplicationProtocols(List<String> protocols);

    /**
     * Gets the current server-side application layer protocol selector.
     *
     * @param the selector mechanism.
     * @return the current application protocol selector, or null if
     *     there is not one.
     */
    public ApplicationProtocolSelector
            getApplicationProtocolSelector() {};

    /**
     * Sets the server-side application layer protocol selector.
     *
     * @param the selector mechanism, or null if protocol selection
     *     should not be done.
     */
    public void setApplicationProtocolSelector(
            ApplicationProtocolSelector selector) {};
}


/*
 * 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;

    /*
     * SSLEngine callback to choose which Application Protocol to return
     * to a SSL/TLS client.
     *
     * @param sslEngine the SSLEngine 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 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(SSLEngine sslEngine, String[] protocols,
            String protocolVersion, String ciphersuite)
            throws SSLProtocolException;
}

If need be, we could include the received extensions or in a future version of this class.


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() { };
}

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.

Thanks,

Brad

Reply via email to