JDK-8062848 : Design and Implementation for JEP 244: TLS Application-Layer Protocol Negotiation Extension
  • Type: Sub-task
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2014-11-04
  • Updated: 2015-12-10
  • Resolved: 2015-12-10
Description
1. Introduction

This feature is to support the Application Layer Protocol Negotiation (ALPN) TLS extension as defined in RFC 7301.


2. Specification

This section describes the integrated API.  (See JDK-8051498 for additional information.)

ALPN configuration and state are currently handled by the javax.net.ssl.SSLParameters and javax.net.ssl.SSLSocket/javax.net.ssl.SSLEngine JSSE classes.  This design defines 6 new public methods for managing application layer protocol names:

 SSLEngine/SSLSocket
===================
    /**
     * Returns the most recent application protocol value negotiated for this
     * connection.
     * <p>
     * If supported by the underlying SSL/TLS/DTLS implementation,
     * application name negotiation mechanisms such as <a
     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
     * Application-Layer Protocol Negotiation (ALPN), can negotiate
     * application-level values between peers.
     * <p>
     * @implSpec
     * The implementation in this class throws
     * {@code UnsupportedOperationException} and performs no other action.
     *
     * @return null if it has not yet been determined if application
     *         protocols might be used for this connection, an empty
     *         {@code String} if application protocols values will not
     *         be used, or a non-empty application protocol {@code String}
     *         if a value was successfully negotiated.
     * @throws UnsupportedOperationException if the underlying provider
     *         does not implement the operation.
     * @since 9
     */
    public String getApplicationProtocol() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the application protocol value negotiated on a SSL/TLS
     * handshake currently in progress.
     * <p>
     * Like {@link #getHandshakeSession()},
     * a connection may be in the middle of a handshake. The
     * application protocol may or may not yet be available.
     * <p>
     * @implSpec
     * The implementation in this class throws
     * {@code UnsupportedOperationException} and performs no other action.
     *
     * @return null if it has not yet been determined if application
     *         protocols might be used for this handshake, an empty
     *         {@code String} if application protocols values will not
     *         be used, or a non-empty application protocol {@code String}
     *         if a value was successfully negotiated.
     * @throws UnsupportedOperationException if the underlying provider
     *         does not implement the operation.
     * @since 9
     */
    public String getHandshakeApplicationProtocol() {
        throw new UnsupportedOperationException();
    }
 
SSLParameters
=============
 
     /**
     * Returns a prioritized array of application-layer protocol names that
     * can be negotiated over the SSL/TLS/DTLS protocols.
     * <p>
     * The array could be empty (zero-length), in which case protocol
     * indications will not be used.
     * <p>
     * This method will return a new array each time it is invoked.
     *
     * @return a non-null, possibly zero-length array of application protocol
     *         {@code String}s.  The array is ordered based on protocol
     *         preference, with {@code protocols[0]} being the most preferred.
     * @see #setApplicationProtocols
     * @since 9
     */
    public String[] getApplicationProtocols() {
        return applicationProtocols.clone();
    }

    /**
     * Sets the prioritized array of application-layer protocol names that
     * can be negotiated over the SSL/TLS/DTLS protocols.
     * <p>
     * If application-layer protocols are supported by the underlying
     * SSL/TLS implementation, this method configures which values can
     * be negotiated by protocols such as <a
     * href="http://www.ietf.org/rfc/rfc7301.txt"> RFC 7301 </a>, the
     * Application Layer Protocol Negotiation (ALPN).
     * <p>
     * If this end of the connection is expected to offer application protocol
     * values, all protocols configured by this method will be sent to the
     * peer.
     * <p>
     * If this end of the connection is expected to select the application
     * protocol value, the {@code protocols} configured by this method are
     * compared with those sent by the peer.  The first matched value becomes
     * the negotiated value.  If none of the {@code protocols} were actually
     * requested by the peer, the underlying protocol will determine what
     * action to take.  (For example, ALPN will send a
     * {@code "no_application_protocol"} alert and terminate the connection.)
     * <p>
     * @implSpec
     * This method will make a copy of the {@code protocols} array.
     *
     * @param protocols   an ordered array of application protocols,
     *                    with {@code protocols[0]} being the most preferred.
     *                    If the array is empty (zero-length), protocol
     *                    indications will not be used.
     * @throws IllegalArgumentException if protocols is null, or if
     *                    any element in a non-empty array is null or an
     *                    empty (zero-length) string
     * @see #getApplicationProtocols
     * @since 9
     */
    public void setApplicationProtocols(String[] protocols) {
        if (protocols == null) {
            throw new IllegalArgumentException("protocols was null");
        }

        String[] tempProtocols = protocols.clone();

        for (String p : tempProtocols) {
            if (p == null || p.equals("")) {
                throw new IllegalArgumentException(
                    "An element of protocols was null/empty");
            }
        }
        applicationProtocols = tempProtocols;
    }


3. Implementation

The following existing JSSE implementation classes are enhanced to support handling of an ALPN extension in the TLS client and server Hello messages:

sun.security.ssl.Alerts.java
sun.security.ssl.ClientHandshaker.java
sun.security.ssl.ExtensionType.java
sun.security.ssl.HandshakeMessage.java
sun.security.ssl.Handshaker.java
sun.security.ssl.HelloExtensions.java
sun.security.ssl.SSLServerSocketImpl.java
sun.security.ssl.SSLSessionImpl.java
sun.security.ssl.SSLSocketImpl.java
sun.security.ssl.ServerHandshaker.java

Along with a new implementation class:

      sun.security.ssl.ALPNExtension implements HelloExtension


4. Issues

ALPN support may be backported to JDK 8 so an implementation is needed that does not introduce any new Java SE 8 APIs.  This may require creating something in a jdk.* or com.oracle.ssl.net package.

Comments
Integrated on 12/9/2015
10-12-2015