JDK-8250965 : Distributed TLS sessions implementation
  • Type: CSR
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Priority: P4
  • Status: Draft
  • Resolution: Unresolved
  • Submitted: 2020-08-03
  • Updated: 2024-11-22
Related Reports
CSR :  
Description
Summary
-------
Implement distributed TLS sessions in JDK.

Problem
-------
In order to increase capacity (concurrent users) and reliability, an application could be deployed on a number of servers. The network connection and application traffics are distributed across the servers. 

A TLS connection is established via TLS handshaking. For an initial connection, the client and server negotiate the secure parameters and then establish the security channel. The negotiation process of the secure parameters is called full handshake. As many cryptographic operations involved, the full handshaking is CPU costly. Fortunately, the negotiated parameters, which is also called as session data, can be reserved for the session, and used for the subsequent connections of the same session. The process to use the negotiated secure parameters is called abbreviate handshake, or session resumption. Per the research, the overall cost of a session resumption is less than 50% of a full handshake, and the CPU cost is almost negligible (less than 5%) compared to the full handshake.

In order to resume the session, the negotiated parameters must be reserved in a certain place. They could be reserved in server cache or in a protected session ticket.

A session ticket is a block of data that is generated and protected by the server, but is not cached in server side. The negotiated parameters could be encapsulated and encrypted in the session ticket, and delivered to client for session resumption. The client will send back the exact session ticket in its session resumption request. The server side retrieves the negotiated parameters by decapsulating and decrypting the received session ticket.

The session ticket standards are defined in RFC 5077 for TLS 1.2 and prior versions, and RFC 8446 for TLS 1.3. However, the RFCs does not define how to construct and protect the session ticket in TLS vendors.

In order to support distributed session resumption, the session ticket generated and protected in one server node, can be used for session resumption in other server node in the distributed system.

As of today, the session ticket generated in JDK is only able to be used in the local host where it is generated. This behavior is not distributed computing friendly, and prevent the use of the SunJSSE provider effectively in distributed systems.

Solution
--------
Per TLS specifications (RFC 8446 and RFC 5077), the session ticket could be designed and implemented to support distributed TLS session resumption. With this proposal, distributed TLS session resumption with session tickets will be supported in JDK.

Specification
--------
1. Provide a session ticket protection scheme.
------------------------
In order to support distributed session resumption, a session ticket that is generated and protected in one server node must be able to be used for session resumption in other server nodes in the distributed system. Each server node should use the same session ticket structure, and share the secrets that used to protect session tickets.

A session ticket protection scheme will be designed and implemented in the SunJSSE provider in JDK. The scheme will support key generation, key rotation and key synchronization across clusters of computers.

The JDK will be ready to support distributed session resumption, if:

 - the same X509KeyManager is used in each node in the distributed system.
 - the X509KeyManager.getServerAliase() method is implemented.
 - there is at least one server alias of which:
    - the certificate chain (X509KeyManager.getCertificateChain(String alias)) is not null or empty, and
    - the private key (X509KeyManager.getPrivateKey(String alias)) is not null, and
    - the private key supports encoding (Key.getEncoded()).

If the key manager does not meet criteria, a session ticket will be protected by a random secret and does not support distributed session resumption.

2. Support distributed session resumption in JDK.
------------------------
Currently, the SunJSSE provider in JDK supports session ticket, but the session ticket cannot be used for distributed session resumption. By using the new session ticket protection scheme, the SunJSSE provider will be updated to support distributed session resumption.

3. Deprecate APIs that impact distributed session resumption.
------------------------
Currently, because local cache is used, the applicaton layer data bound to the session could be a problem for fully support of distributed session resumption.  Fortunately, the use of these methods may not be common, and applications could replace them with application layer code. These methods in SSLSession class could be deprecated.

        /**
         * Binds the specified {@code value} object into the session's application
         * layer data with the given {@code name}.
         * <P>
         * Any existing binding using the same {@code name} is
         * replaced.  If the new (or existing) {@code value} implements the
         * {@code SSLSessionBindingListener} interface, the object
         * represented by {@code value} is notified appropriately.
         * <p>
         * For security reasons, the same named values may not be
         * visible across different access control contexts.
         *
         * @param name the name to which the data object will be bound.
         *          This may not be null.
         * @param value the data object to be bound. This may not be null.
         * @throws IllegalArgumentException if either argument is null.
    +    *
    +    * @deprecated Please handle application data in application layer.
         */
    +   @Deprecated(since="16")
        public void putValue(String name, Object value);

        /**
         * Returns the object bound to the given name in the session's
         * application layer data.  Returns null if there is no such binding.
         * <p>
         * For security reasons, the same named values may not be
         * visible across different access control contexts.
         *
         * @param name the name of the binding to find.
         * @return the value bound to that name, or null if the binding does
         *          not exist.
         * @throws IllegalArgumentException if the argument is null.
    +    *
    +    * @deprecated Please handle application data in application layer.
         */
    +   @Deprecated(since="16")
        public Object getValue(String name);

        /**
         * Removes the object bound to the given name in the session's
         * application layer data.  Does nothing if there is no object
         * bound to the given name.  If the bound existing object
         * implements the {@code SSLSessionBindingListener} interface,
         * it is notified appropriately.
         * <p>
         * For security reasons, the same named values may not be
         * visible across different access control contexts.
         *
         * @param name the name of the object to remove visible
         *          across different access control contexts
         * @throws IllegalArgumentException if the argument is null.
    +    *
    +    * @deprecated Please handle application data in application layer.
         */
    +   @Deprecated(since="16")
        public void removeValue(String name);

        /**
         * Returns an array of the names of all the application layer
         * data objects bound into the Session.
         * <p>
         * For security reasons, the same named values may not be
         * visible across different access control contexts.
         *
         * @return a non-null (possibly empty) array of names of the objects
         *  bound to this Session.
    +    *
    +    * @deprecated Please handle application data in application layer.
         */
    +   @Deprecated(since="16")
        public String[] getValueNames();

4. Add a new System Property to turn off this feature.
------------------------
A new System Property, "jdk.tls.server.useDistributedSessions", will be added to turn off this feature if needed.   The default value is "true".  If it is set to "false", the default distributed session resumption implementation in JDK is turned off, and a session ticket can only be used in the node where it was generated. 

5. Mitigate the session cache collisions
------------------------
In the current JDK implementation, the client cached session is indexed with server host and port, without considering other connection properties like server name indication and application layer protocols.  In practice, a client, for example HTTP client, may open multiple connections.  The last success connection will be overridden and the last failed may erase the session in the cache.  The session resumption may never work as expected in multiple thread multiple connections circumstances.

With this update, the session indexing ID will be calculated by considering more properties.  This update should be transparent to applications.  There is no expected compatibility impact.

Documentation
--------
The session ticket protection scheme should be documented in the JSSE Reference Guides, with proper instructions and examples.

It may worthy of adding a implNote or apiNote tag in the javax.net.ssl.SSLContext class.  It will be considered later if needed.