JDK-8245609 : Default SSLEngine should create in server role
  • Type: CSR
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Priority: P2
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 11-pool,14-pool
  • Submitted: 2020-05-22
  • Updated: 2020-05-27
  • Resolved: 2020-05-27
Related Reports
CSR :  
Relates :  
Description
Summary
-------
Request to change the default SSLEngine role to server mode.

No changes from 15 CSR, JDK-8238593.

Problem
-------
In JDK 11, the default SSLEngine role is updated from server mode to client mode, which is not intended.  As the role must be set explicitly with
SSLEngine.setUseClientMode() before the connection could be established, it is not expected to have compatibility impact.

However, it is missed that the SSLEngine.setUseClientMode() method may be not the first method called after SSLEngine get instantiated.  For some use cases when application want to use the parameters before setting the rols, there are actually some compatibility impact.

For example, application can call SSLEngine.getEnabledProtocols���() and then SSLEngine.setEnabledProtocols���() accordingly, and then call SSLEngine.setUseClientMode(). The returned value of SSLEngine.getEnabledProtocols���() for client mode is different from the server mode.  As could result compatibility issues.


Solution
--------
1. Revert the default SSLEngine role to server mode, as it is in JDK 10 and prior releases.
2. Add implementation notes to the specification to avoid the calling sequence issue in the future.
3. A release note describing this change will accompany the affected JDK releases

Specification
--------
1. Add implementation note to SSLContext.createSSLEngine()

             /**
              * Creates a new {@code SSLEngine} using this context.
              * <P>
              * Applications using this factory method are providing no hints
              * for an internal session reuse strategy. If hints are desired,
              * {@link #createSSLEngine(String, int)} should be used
              * instead.
              * <P>
              * Some cipher suites (such as Kerberos) require remote hostname
              * information, in which case this factory method should not be used.
              *
        +     * @implNote
        +     * It is provider-specific if the returned SSLEngine uses client or
        +     * server mode by default for the (D)TLS connection. The JDK SunJSSE
        +     * provider implementation uses server mode by default.  However, it
        +     * is recommended to always set the desired mode explicitly by calling
        +     * {@link SSLEngine#setUseClientMode(boolean) SSLEngine.setUseClientMode()}
        +     * before invoking other methods of the SSLEngine.
        +     *
              * @return  the {@code SSLEngine} object
              * @throws  UnsupportedOperationException if the underlying provider
              *          does not implement the operation.
              * @throws  IllegalStateException if the SSLContextImpl requires
              *          initialization and the {@code init()} has not been called
              * @since   1.5
              */
             public final SSLEngine createSSLEngine() {

2. Add implementation note to SSLContext.createSSLEngine(createSSLEngine(String peerHost, int peerPort)

            /**
             * Creates a new {@code SSLEngine} using this context using
             * advisory peer information.
             * <P>
             * Applications using this factory method are providing hints
             * for an internal session reuse strategy.
             * <P>
             * Some cipher suites (such as Kerberos) require remote hostname
             * information, in which case peerHost needs to be specified.
             *
        +    * @implNote
        +    * It is provider-specific if the returned SSLEngine uses client or
        +    * server mode by default for the (D)TLS connection. The JDK SunJSSE
        +    * provider implementation uses server mode by default.  However, it
        +    * is recommended to always set the desired mode explicitly by calling
        +    * {@link SSLEngine#setUseClientMode(boolean) SSLEngine.setUseClientMode()}
        +    * before invoking other methods of the SSLEngine.
        +    *
             * @param   peerHost the non-authoritative name of the host
             * @param   peerPort the non-authoritative port
             * @return  the new {@code SSLEngine} object
             * @throws  UnsupportedOperationException if the underlying provider
             *          does not implement the operation.
             * @throws  IllegalStateException if the SSLContextImpl requires
             *          initialization and the {@code init()} has not been called
             * @since   1.5
             */
            public final SSLEngine createSSLEngine(String peerHost, int peerPort) {

3. Add implementation note to SSLContextSpi.engineCreateSSLEngine()

            /**
             * Creates a new {@code SSLEngine} using this context.
             * <P>
             * Applications using this factory method are providing no hints
             * for an internal session reuse strategy. If hints are desired,
             * {@link #engineCreateSSLEngine(String, int)} should be used
             * instead.
             * <P>
             * Some cipher suites (such as Kerberos) require remote hostname
             * information, in which case this factory method should not be used.
             *
        +    * @implNote
        +    * It is provider-specific if the returned SSLEngine uses client or
        +    * server mode by default for the (D)TLS connection. The JDK SunJSSE
        +    * provider implementation uses server mode by default.  However, it
        +    * is recommended to always set the desired mode explicitly by calling
        +    * {@link SSLEngine#setUseClientMode(boolean) SSLEngine.setUseClientMode()}
        +    * before invoking other methods of the SSLEngine.
        +    *
             * @return  the {@code SSLEngine} Object
             * @throws IllegalStateException if the SSLContextImpl requires
             *         initialization and the {@code engineInit()}
             *         has not been called
             *
             * @see     SSLContext#createSSLEngine()
             *
             * @since   1.5
             */
            protected abstract SSLEngine engineCreateSSLEngine();

4. Add implementation note to SSLContextSpi.engineCreateSSLEngine(String host, int port)

            /**
             * Creates a {@code SSLEngine} using this context.
             * <P>
             * Applications using this factory method are providing hints
             * for an internal session reuse strategy.
             * <P>
             * Some cipher suites (such as Kerberos) require remote hostname
             * information, in which case peerHost needs to be specified.
             *
        +    * @implNote
        +    * It is provider-specific if the returned SSLEngine uses client or
        +    * server mode by default for the (D)TLS connection. The JDK SunJSSE
        +    * provider implementation uses server mode by default.  However, it
        +    * is recommended to always set the desired mode explicitly by calling
        +    * {@link SSLEngine#setUseClientMode(boolean) SSLEngine.setUseClientMode()}
        +    * before invoking other methods of the SSLEngine.
        +    *
             * @param host the non-authoritative name of the host
             * @param port the non-authoritative port
             * @return  the {@code SSLEngine} Object
             * @throws IllegalStateException if the SSLContextImpl requires
             *         initialization and the {@code engineInit()}
             *         has not been called
             *
             * @see     SSLContext#createSSLEngine(String, int)
             *
             * @since   1.5
             */
            protected abstract SSLEngine engineCreateSSLEngine(String host, int port);

5. Add implementation note to SSLEngine class specification

            * <P>
            * Each SSL/TLS/DTLS connection must have one client and one server, thus
            * each endpoint must decide which role to assume.  This choice determines
            * who begins the handshaking process as well as which type of messages
            * should be sent by each party.  The method {@link
        -   * #setUseClientMode(boolean)} configures the mode.  Once the initial
        -   * handshaking has started, an {@code SSLEngine} can not switch
        -   * between client and server modes, even when performing renegotiations.
        +   * #setUseClientMode(boolean)} configures the mode.  Note that the
        +   * default mode for a new {@code SSLEngine} object is provider-specific.
        +   * Applications should set the mode explicitly before invoking other
        +   * methods of the {@code SSLEngine}.  Once the initial handshaking has
        +   * started, an {@code SSLEngine} can not switch between client and server
        +   * modes, even when performing renegotiations.
            * <P>

6. Add implementation note to SSLEngine.getUseClientMode()

            /**
             * Returns true if the engine is set to use client mode when
             * handshaking.
             *
        +    * @implNote
        +    * The JDK SunJSSE provider implementation returns false unless {@link setUseClientMode} 
        +    *          is used to change the mode to true.
        +    *
             * @return  true if the engine should do handshaking
             *          in "client" mode
             * @see     #setUseClientMode(boolean)
             */
            public abstract boolean getUseClientMode();

7. Add implementation note to SSLEngine.setUseClientMode(boolean)

            /**
             * Configures the engine to use client (or server) mode when
             * handshaking.
             * <P>
             * This method must be called before any handshaking occurs.
             * Once handshaking has begun, the mode can not be reset for the
             * life of this engine.
             * <P>
             * Servers normally authenticate themselves, and clients
             * are not required to do so.
             *
        +    * @implNote
        +    * The JDK SunJSSE provider implementation default for this mode is false.
        +    *
             * @param   mode true if the engine should start its handshaking
             *          in "client" mode
             * @throws  IllegalArgumentException if a mode change is attempted
             *          after the initial handshake has begun.
             * @see     #getUseClientMode()
             */
            public abstract void setUseClientMode(boolean mode);
Comments
Moving to Approved.
27-05-2020

Except backport info in solution section, no changes from 15 CSR. Fix is part of 8u261 and 11.0.8-oracle.
22-05-2020