Skip to content

Public API to configure TLS named groups at SSLContext or SSLSocket/SSLEngine level in Java < 20 #1500

@diegomarquezp

Description

@diegomarquezp

Description

Context

We are migrating to Post-Quantum Cryptography (PQC) in googleapis/google-http-java-client and possibly in grpc-java (not owned). We'd like to use Conscrypt and specify the named groups (mainly X25519MLKEM768) specific to the SSLContext or SSLSockets created by our library, since it seems they are not advertised by default.

We support Java 8, 11, 17, 21, and 25.

The Problem

SSLParameters.setNamedGroups(String[]) is only available in Java 20+. In Java 8, 11, and 17, SSLParameters lacks a public method to configure named groups. Using the global-scoped system properties may pollute other dependencies or user code.

Conscrypt does not expose a public API to configure named groups on a specific SSLContext, SSLSocket, or SSLEngine instance.

Because of this, we must use JCA reflection to bypass class visibility, retrieve internal fields, and invoke package-private methods.

So far I could come up with a way to force the named groups local to the SSLSockets:

  1. Check if socket is ConscryptFileDescriptorSocket or ConscryptEngineSocket (or subclass Java8EngineSocket).
  2. Retrieve the private field sslParameters (or engine.sslParameters).
  3. Retrieve package-private method void setNamedGroups(String[]) on org.conscrypt.SSLParametersImpl.
  4. Invoke the method.

Code:

  private void configureConscryptNamedGroups(javax.net.ssl.SSLSocket socket) {
    try {
      Class<?> fileDescClass = Class.forName("org.conscrypt.ConscryptFileDescriptorSocket");
      Class<?> engineSocketClass = Class.forName("org.conscrypt.ConscryptEngineSocket");
      Object sslParametersImpl = null;

      if (fileDescClass.isInstance(socket)) {
        Field f = fileDescClass.getDeclaredField("sslParameters");
        f.setAccessible(true);
        sslParametersImpl = f.get(socket);
      } else if (engineSocketClass.isInstance(socket)) {
        Field fEngine = engineSocketClass.getDeclaredField("engine");
        fEngine.setAccessible(true);
        Object engine = fEngine.get(socket);
        if (engine != null) {
          Class<?> engineClass = Class.forName("org.conscrypt.ConscryptEngine");
          Field fParams = engineClass.getDeclaredField("sslParameters");
          fParams.setAccessible(true);
          sslParametersImpl = fParams.get(engine);
        }
      }

      if (sslParametersImpl != null) {
        Class<?> paramsClass = Class.forName("org.conscrypt.SSLParametersImpl");
        Method setNamedGroupsMethod = paramsClass.getDeclaredMethod("setNamedGroups", String[].class);
        setNamedGroupsMethod.setAccessible(true);
        setNamedGroupsMethod.invoke(sslParametersImpl, (Object) new String[] {"X25519MLKEM768", "x25519"});
      }
    } catch (Exception e) {
      // Fallback
    }
  }

Question

I'd like to confirm whether there are ways to set named groups specific to the SSLContexts created by Conscrypt. If not would introducing such a surface be reasonable?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions