This is an automated email from the ASF dual-hosted git repository.

HTHou pushed a commit to branch codex/generic-ssl-config
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit e33598335c4e4a8162a37b41d0965181b456ec1c
Author: HTHou <[email protected]>
AuthorDate: Fri Jun 5 18:44:03 2026 +0800

    Add generic SSL TLS configuration support
---
 .../java/org/apache/iotdb/rest/RestService.java    |  24 ++
 .../java/org/apache/iotdb/cli/AbstractCli.java     |  32 ++
 .../src/main/java/org/apache/iotdb/cli/Cli.java    |   8 +
 .../org/apache/iotdb/tool/common/Constants.java    |   8 +
 .../org/apache/iotdb/tool/common/OptionsUtil.java  |  20 +
 .../apache/iotdb/tool/data/AbstractDataTool.java   |  51 +++
 .../apache/iotdb/tool/data/ExportDataTable.java    |   3 +-
 .../org/apache/iotdb/tool/data/ExportDataTree.java |   3 +-
 .../apache/iotdb/tool/data/ImportDataTable.java    |   3 +-
 .../org/apache/iotdb/tool/data/ImportDataTree.java |   3 +-
 .../iotdb/tool/schema/AbstractSchemaTool.java      |  39 ++
 .../iotdb/tool/schema/ExportSchemaTable.java       |   3 +-
 .../apache/iotdb/tool/schema/ExportSchemaTree.java |   3 +-
 .../iotdb/tool/schema/ImportSchemaTable.java       |   3 +-
 .../apache/iotdb/tool/schema/ImportSchemaTree.java |   3 +-
 .../org/apache/iotdb/isession/SessionConfig.java   |   4 +
 .../main/java/org/apache/iotdb/jdbc/Config.java    |   8 +
 .../org/apache/iotdb/jdbc/IoTDBConnection.java     |   6 +-
 .../apache/iotdb/jdbc/IoTDBConnectionParams.java   |  18 +
 .../src/main/java/org/apache/iotdb/jdbc/Utils.java |   8 +
 .../test/java/org/apache/iotdb/jdbc/UtilsTest.java |  14 +
 .../apache/iotdb/rpc/BaseRpcTransportFactory.java  |  49 ++-
 .../java/org/apache/iotdb/rpc/RpcSslUtils.java     | 422 +++++++++++++++++++++
 .../iotdb/session/AbstractSessionBuilder.java      |   2 +
 .../org/apache/iotdb/session/NodesSupplier.java    |  12 +
 .../java/org/apache/iotdb/session/Session.java     |  16 +
 .../apache/iotdb/session/SessionConnection.java    |  38 +-
 .../apache/iotdb/session/TableSessionBuilder.java  |  24 ++
 .../org/apache/iotdb/session/ThriftConnection.java |   8 +-
 .../org/apache/iotdb/session/pool/SessionPool.java |  25 ++
 .../session/pool/TableSessionPoolBuilder.java      |  24 ++
 .../apache/iotdb/consensus/ratis/utils/Utils.java  |  30 +-
 .../iotdb/db/conf/rest/IoTDBRestServiceConfig.java |  22 ++
 .../db/conf/rest/IoTDBRestServiceDescriptor.java   |   3 +
 .../conf/iotdb-system.properties.template          |  20 +
 .../apache/iotdb/commons/conf/CommonConfig.java    |  33 ++
 .../iotdb/commons/conf/CommonDescriptor.java       |  12 +
 .../service/AbstractThriftServiceThread.java       |  52 +--
 38 files changed, 954 insertions(+), 102 deletions(-)

diff --git 
a/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/RestService.java
 
b/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/RestService.java
index 2e072d87961..85d0ee4476a 100644
--- 
a/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/RestService.java
+++ 
b/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/RestService.java
@@ -21,6 +21,7 @@ import 
org.apache.iotdb.db.conf.rest.IoTDBRestServiceDescriptor;
 import org.apache.iotdb.externalservice.api.IExternalService;
 import org.apache.iotdb.rest.i18n.RestMessages;
 import org.apache.iotdb.rest.protocol.filter.ApiOriginFilter;
+import org.apache.iotdb.rpc.RpcSslUtils;
 
 import org.eclipse.jetty.http.HttpVersion;
 import org.eclipse.jetty.server.HttpConfiguration;
@@ -52,6 +53,8 @@ public class RestService implements IExternalService {
       String trustStorePath,
       String keyStorePwd,
       String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass,
       int idleTime,
       boolean clientAuth) {
     server = new Server();
@@ -61,6 +64,7 @@ public class RestService implements IExternalService {
     httpsConfig.addCustomizer(new SecureRequestCustomizer());
 
     SslContextFactory.Server sslContextFactory = new 
SslContextFactory.Server();
+    configureSSL(sslContextFactory, sslProtocol, sslProviderClass);
     sslContextFactory.setKeyStorePath(keyStorePath);
     sslContextFactory.setKeyStorePassword(keyStorePwd);
     if (clientAuth) {
@@ -125,6 +129,8 @@ public class RestService implements IExternalService {
           config.getTrustStorePath(),
           config.getKeyStorePwd(),
           config.getTrustStorePwd(),
+          config.getSslProtocol(),
+          config.getSslProviderClass(),
           config.getIdleTimeoutInSeconds(),
           config.isClientAuth());
     } else {
@@ -142,4 +148,22 @@ public class RestService implements IExternalService {
       server.destroy();
     }
   }
+
+  private void configureSSL(
+      SslContextFactory.Server sslContextFactory, String sslProtocol, String 
sslProviderClass) {
+    String protocol = trimToEmpty(sslProtocol);
+    try {
+      RpcSslUtils.ensureProvider(protocol, sslProviderClass);
+    } catch (Exception e) {
+      throw new IllegalArgumentException("Failed to initialize SSL provider 
for REST service", e);
+    }
+    if (!protocol.isEmpty()) {
+      sslContextFactory.setProtocol(protocol);
+      sslContextFactory.setIncludeProtocols(protocol);
+    }
+  }
+
+  private String trimToEmpty(String value) {
+    return value == null ? "" : value.trim();
+  }
 }
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/AbstractCli.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/AbstractCli.java
index 22ecdc3a40e..1f079450f5a 100644
--- a/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/AbstractCli.java
+++ b/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/AbstractCli.java
@@ -77,12 +77,18 @@ public abstract class AbstractCli {
 
   static final String TRUST_STORE_PWD_ARGS = "tpw";
 
+  static final String SSL_PROTOCOL_ARGS = "ssl_protocol";
+
+  static final String SSL_PROVIDER_CLASS_ARGS = "ssl_provider_class";
+
   private static final String EXECUTE_NAME = "execute";
 
   private static final String USE_SSL = "use_ssl";
   private static final String TRUST_STORE = "trust_store";
 
   private static final String TRUST_STORE_PWD = "trust_store_pwd";
+  private static final String SSL_PROTOCOL = "ssl_protocol";
+  private static final String SSL_PROVIDER_CLASS = "ssl_provider_class";
   private static final String NULL = "null";
 
   static final int CODE_OK = 0;
@@ -132,6 +138,10 @@ public abstract class AbstractCli {
   static String trustStore;
   // TODO: Make non-static
   static String trustStorePwd;
+  // TODO: Make non-static
+  static String sslProtocol;
+  // TODO: Make non-static
+  static String sslProviderClass;
 
   static String execute;
   static boolean hasExecuteSQL = false;
@@ -156,6 +166,10 @@ public abstract class AbstractCli {
     keywordSet.add("-" + USE_SSL_ARGS);
     keywordSet.add("-" + TRUST_STORE_ARGS);
     keywordSet.add("-" + TRUST_STORE_PWD_ARGS);
+    keywordSet.add("-" + SSL_PROTOCOL_ARGS);
+    keywordSet.add("--" + SSL_PROTOCOL_ARGS);
+    keywordSet.add("-" + SSL_PROVIDER_CLASS_ARGS);
+    keywordSet.add("--" + SSL_PROVIDER_CLASS_ARGS);
     keywordSet.add("-" + EXECUTE_ARGS);
     keywordSet.add("-" + ISO8601_ARGS);
     keywordSet.add("-" + RPC_COMPRESS_ARGS);
@@ -214,6 +228,24 @@ public abstract class AbstractCli {
             .build();
     options.addOption(useSSL);
 
+    Option sslProtocol =
+        Option.builder(SSL_PROTOCOL_ARGS)
+            .longOpt(SSL_PROTOCOL)
+            .argName(SSL_PROTOCOL)
+            .hasArg()
+            .desc("SSL protocol. (optional)")
+            .build();
+    options.addOption(sslProtocol);
+
+    Option sslProviderClass =
+        Option.builder(SSL_PROVIDER_CLASS_ARGS)
+            .longOpt(SSL_PROVIDER_CLASS)
+            .argName(SSL_PROVIDER_CLASS)
+            .hasArg()
+            .desc("JSSE provider class for SSL. (optional)")
+            .build();
+    options.addOption(sslProviderClass);
+
     Option execute =
         Option.builder(EXECUTE_ARGS)
             .argName(EXECUTE_NAME)
diff --git a/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/Cli.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/Cli.java
index d1bbd6165f6..f4e3e6bdfdd 100644
--- a/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/Cli.java
+++ b/iotdb-client/cli/src/main/java/org/apache/iotdb/cli/Cli.java
@@ -111,6 +111,12 @@ public class Cli extends AbstractCli {
       info.setProperty("use_ssl", useSsl);
       info.setProperty("trust_store", trustStore);
       info.setProperty("trust_store_pwd", trustStorePwd);
+      if (sslProtocol != null) {
+        info.setProperty(Config.SSL_PROTOCOL, sslProtocol);
+      }
+      if (sslProviderClass != null) {
+        info.setProperty(Config.SSL_PROVIDER_CLASS, sslProviderClass);
+      }
     }
     info.setProperty("user", username);
     info.setProperty("password", password);
@@ -159,6 +165,8 @@ public class Cli extends AbstractCli {
   private static void serve(CliContext ctx) {
     try {
       useSsl = commandLine.getOptionValue(USE_SSL_ARGS);
+      sslProtocol = commandLine.getOptionValue(SSL_PROTOCOL_ARGS);
+      sslProviderClass = commandLine.getOptionValue(SSL_PROVIDER_CLASS_ARGS);
       if (Boolean.parseBoolean(useSsl)) {
         trustStore = ctx.getLineReader().readLine("please input your 
trust_store:", '\0');
         trustStorePwd = ctx.getLineReader().readLine("please input your 
trust_store_pwd:", '\0');
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/Constants.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/Constants.java
index 0d4c5f218b7..56c34dbdf03 100644
--- a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/Constants.java
+++ b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/Constants.java
@@ -68,6 +68,14 @@ public class Constants {
   public static final String TRUST_STORE_PWD_NAME = "trust_store_password";
   public static final String TRUST_STORE_PWD_DESC = "Trust store password. 
(optional)";
 
+  public static final String SSL_PROTOCOL_ARGS = "ssl_protocol";
+  public static final String SSL_PROTOCOL_NAME = "ssl_protocol";
+  public static final String SSL_PROTOCOL_DESC = "SSL protocol. (optional)";
+
+  public static final String SSL_PROVIDER_CLASS_ARGS = "ssl_provider_class";
+  public static final String SSL_PROVIDER_CLASS_NAME = "ssl_provider_class";
+  public static final String SSL_PROVIDER_CLASS_DESC = "JSSE provider class 
for SSL. (optional)";
+
   public static final String FILE_TYPE_ARGS = "ft";
   public static final String FILE_TYPE_NAME = "file_type";
   public static final String FILE_TYPE_ARGS_NAME = "format";
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/OptionsUtil.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/OptionsUtil.java
index b60809eba63..acbac88afbe 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/OptionsUtil.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/common/OptionsUtil.java
@@ -133,6 +133,26 @@ public class OptionsUtil extends Constants {
             .build();
     options.addOption(opTrustStorePwd);
 
+    Option opSslProtocol =
+        Option.builder(SSL_PROTOCOL_ARGS)
+            .longOpt(SSL_PROTOCOL_NAME)
+            .optionalArg(true)
+            .argName(SSL_PROTOCOL_NAME)
+            .hasArg()
+            .desc(SSL_PROTOCOL_DESC)
+            .build();
+    options.addOption(opSslProtocol);
+
+    Option opSslProviderClass =
+        Option.builder(SSL_PROVIDER_CLASS_ARGS)
+            .longOpt(SSL_PROVIDER_CLASS_NAME)
+            .optionalArg(true)
+            .argName(SSL_PROVIDER_CLASS_NAME)
+            .hasArg()
+            .desc(SSL_PROVIDER_CLASS_DESC)
+            .build();
+    options.addOption(opSslProviderClass);
+
     return options;
   }
 
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/AbstractDataTool.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/AbstractDataTool.java
index 4ef95c78eda..5a9b14f3337 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/AbstractDataTool.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/AbstractDataTool.java
@@ -34,6 +34,9 @@ import org.apache.iotdb.isession.SessionDataSet;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 import org.apache.iotdb.session.Session;
+import org.apache.iotdb.session.TableSessionBuilder;
+import org.apache.iotdb.session.pool.SessionPool;
+import org.apache.iotdb.session.pool.TableSessionPoolBuilder;
 import org.apache.iotdb.tool.common.Constants;
 import org.apache.iotdb.tool.common.ImportTsFileOperation;
 
@@ -94,6 +97,8 @@ public abstract class AbstractDataTool {
   protected static Boolean useSsl;
   protected static String trustStore;
   protected static String trustStorePwd;
+  protected static String sslProtocol;
+  protected static String sslProviderClass;
   protected static Boolean aligned;
   protected static String database;
   protected static String startTime;
@@ -134,6 +139,50 @@ public abstract class AbstractDataTool {
 
   protected AbstractDataTool() {}
 
+  protected static Session.Builder configureSsl(Session.Builder builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
+  protected static SessionPool.Builder configureSsl(SessionPool.Builder 
builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
+  protected static TableSessionBuilder configureSsl(TableSessionBuilder 
builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
+  protected static TableSessionPoolBuilder 
configureSsl(TableSessionPoolBuilder builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
   protected static String checkRequiredArg(
       String arg, String name, CommandLine commandLine, String defaultValue)
       throws ArgsErrorException {
@@ -170,6 +219,8 @@ public abstract class AbstractDataTool {
     String useSslStr = commandLine.getOptionValue(Constants.USE_SSL_ARGS);
     useSsl = Boolean.parseBoolean(useSslStr);
     if (useSsl) {
+      sslProtocol = commandLine.getOptionValue(Constants.SSL_PROTOCOL_ARGS);
+      sslProviderClass = 
commandLine.getOptionValue(Constants.SSL_PROVIDER_CLASS_ARGS);
       String givenTS = commandLine.getOptionValue(Constants.TRUST_STORE_ARGS);
       if (givenTS != null) {
         trustStore = givenTS;
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTable.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTable.java
index dcf05baa14e..458c447ba4f 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTable.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTable.java
@@ -71,8 +71,7 @@ public class ExportDataTable extends AbstractExportData {
             .database(database)
             .thriftMaxFrameSize(rpcMaxFrameSize);
     if (useSsl) {
-      tableSessionBuilder =
-          
tableSessionBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      tableSessionBuilder = configureSsl(tableSessionBuilder);
     }
     tableSession = tableSessionBuilder.build();
     SessionDataSet sessionDataSet = tableSession.executeQueryStatement("show 
databases", timeout);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTree.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTree.java
index 9d7d0ca521d..fd8aeb0cbe3 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTree.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ExportDataTree.java
@@ -80,8 +80,7 @@ public class ExportDataTree extends AbstractExportData {
             .enableRedirection(SessionConfig.DEFAULT_REDIRECTION_MODE)
             .version(SessionConfig.DEFAULT_VERSION);
     if (useSsl) {
-      sessionBuilder =
-          
sessionBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      sessionBuilder = configureSsl(sessionBuilder);
     }
     session = sessionBuilder.build();
     session.open(false);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTable.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTable.java
index 506da8b8e17..d103c63555b 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTable.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTable.java
@@ -88,8 +88,7 @@ public class ImportDataTable extends AbstractImportData {
             .enableAutoFetch(false)
             .database(database);
     if (useSsl) {
-      tableSessionPoolBuilder =
-          
tableSessionPoolBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      tableSessionPoolBuilder = configureSsl(tableSessionPoolBuilder);
     }
     sessionPool = tableSessionPoolBuilder.build();
     final File file = new File(targetPath);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTree.java 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTree.java
index 95aa9263142..c976e847740 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTree.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/data/ImportDataTree.java
@@ -72,8 +72,7 @@ public class ImportDataTree extends AbstractImportData {
             .enableRedirection(false)
             .enableAutoFetch(false);
     if (useSsl) {
-      sessionPoolBuilder =
-          
sessionPoolBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      sessionPoolBuilder = configureSsl(sessionPoolBuilder);
     }
     sessionPool = sessionPoolBuilder.build();
     sessionPool.setEnableQueryRedirection(false);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/AbstractSchemaTool.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/AbstractSchemaTool.java
index 09442bdab87..7a18b84f559 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/AbstractSchemaTool.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/AbstractSchemaTool.java
@@ -25,6 +25,8 @@ import org.apache.iotdb.cli.utils.IoTPrinter;
 import org.apache.iotdb.cli.utils.JlineUtils;
 import org.apache.iotdb.exception.ArgsErrorException;
 import org.apache.iotdb.session.Session;
+import org.apache.iotdb.session.pool.SessionPool;
+import org.apache.iotdb.session.pool.TableSessionPoolBuilder;
 import org.apache.iotdb.tool.common.Constants;
 
 import org.apache.commons.cli.CommandLine;
@@ -53,6 +55,8 @@ public abstract class AbstractSchemaTool {
   protected static Boolean useSsl;
   protected static String trustStore;
   protected static String trustStorePwd;
+  protected static String sslProtocol;
+  protected static String sslProviderClass;
   protected static Session session;
   protected static String queryPath;
   protected static int threadNum = 8;
@@ -73,6 +77,39 @@ public abstract class AbstractSchemaTool {
 
   protected AbstractSchemaTool() {}
 
+  protected static Session.Builder configureSsl(Session.Builder builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
+  protected static SessionPool.Builder configureSsl(SessionPool.Builder 
builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
+  protected static TableSessionPoolBuilder 
configureSsl(TableSessionPoolBuilder builder) {
+    builder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+    if (sslProtocol != null) {
+      builder.sslProtocol(sslProtocol);
+    }
+    if (sslProviderClass != null) {
+      builder.sslProviderClass(sslProviderClass);
+    }
+    return builder;
+  }
+
   protected static String checkRequiredArg(
       String arg, String name, CommandLine commandLine, String defaultValue)
       throws ArgsErrorException {
@@ -107,6 +144,8 @@ public abstract class AbstractSchemaTool {
     String useSslStr = commandLine.getOptionValue(Constants.USE_SSL_ARGS);
     useSsl = Boolean.parseBoolean(useSslStr);
     if (useSsl) {
+      sslProtocol = commandLine.getOptionValue(Constants.SSL_PROTOCOL_ARGS);
+      sslProviderClass = 
commandLine.getOptionValue(Constants.SSL_PROVIDER_CLASS_ARGS);
       String givenTS = commandLine.getOptionValue(Constants.TRUST_STORE_ARGS);
       if (givenTS != null) {
         trustStore = givenTS;
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTable.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTable.java
index 1ed3e2c6b86..c9b15870d21 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTable.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTable.java
@@ -64,8 +64,7 @@ public class ExportSchemaTable extends AbstractExportSchema {
             .enableAutoFetch(false)
             .database(database);
     if (useSsl) {
-      tableSessionPoolBuilder =
-          
tableSessionPoolBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      tableSessionPoolBuilder = configureSsl(tableSessionPoolBuilder);
     }
     sessionPool = tableSessionPoolBuilder.build();
     checkDatabase();
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTree.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTree.java
index 334d8a8d8dc..da304f87c49 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTree.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ExportSchemaTree.java
@@ -51,8 +51,7 @@ public class ExportSchemaTree extends AbstractExportSchema {
             .username(username)
             .password(password);
     if (useSsl) {
-      sessionBuilder =
-          
sessionBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      sessionBuilder = configureSsl(sessionBuilder);
     }
     session = sessionBuilder.build();
     session.open(false);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTable.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTable.java
index 011042c34d2..004ec8b4152 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTable.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTable.java
@@ -60,8 +60,7 @@ public class ImportSchemaTable extends AbstractImportSchema {
             .enableAutoFetch(false)
             .database(database);
     if (useSsl) {
-      tableSessionPoolBuilder =
-          
tableSessionPoolBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      tableSessionPoolBuilder = configureSsl(tableSessionPoolBuilder);
     }
     sessionPool = tableSessionPoolBuilder.build();
     final File file = new File(targetPath);
diff --git 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTree.java
 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTree.java
index 9526447fd96..5d7dfc35d8a 100644
--- 
a/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTree.java
+++ 
b/iotdb-client/cli/src/main/java/org/apache/iotdb/tool/schema/ImportSchemaTree.java
@@ -73,8 +73,7 @@ public class ImportSchemaTree extends AbstractImportSchema {
             .enableRedirection(false)
             .enableAutoFetch(false);
     if (useSsl) {
-      sessionPoolBuilder =
-          
sessionPoolBuilder.useSSL(true).trustStore(trustStore).trustStorePwd(trustStorePwd);
+      sessionPoolBuilder = configureSsl(sessionPoolBuilder);
     }
     sessionPool = sessionPoolBuilder.build();
     sessionPool.setEnableQueryRedirection(false);
diff --git 
a/iotdb-client/isession/src/main/java/org/apache/iotdb/isession/SessionConfig.java
 
b/iotdb-client/isession/src/main/java/org/apache/iotdb/isession/SessionConfig.java
index 611014c615c..0a577c45f2d 100644
--- 
a/iotdb-client/isession/src/main/java/org/apache/iotdb/isession/SessionConfig.java
+++ 
b/iotdb-client/isession/src/main/java/org/apache/iotdb/isession/SessionConfig.java
@@ -56,5 +56,9 @@ public class SessionConfig {
 
   public static final String SQL_DIALECT = "tree";
 
+  public static final String DEFAULT_SSL_PROTOCOL = "TLS";
+
+  public static final String DEFAULT_SSL_PROVIDER_CLASS = "";
+
   private SessionConfig() {}
 }
diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
index 0b1049330ea..5aaf0f68366 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
@@ -82,6 +82,14 @@ public class Config {
 
   public static final String TRUST_STORE_PWD = "trust_store_pwd";
 
+  public static final String SSL_PROTOCOL = "ssl_protocol";
+
+  public static final String SSL_PROVIDER_CLASS = "ssl_provider_class";
+
+  static final String DEFAULT_SSL_PROTOCOL = "TLS";
+
+  static final String DEFAULT_SSL_PROVIDER_CLASS = "";
+
   public static final String SQL_DIALECT = "sql_dialect";
 
   public static final String DATABASE = "db";
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
index 7f37e2206fb..9b95939864d 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
@@ -544,12 +544,14 @@ public class IoTDBConnection implements Connection {
 
     if (params.isUseSSL()) {
       transport =
-          DeepCopyRpcTransportFactory.INSTANCE.getTransport(
+          DeepCopyRpcTransportFactory.INSTANCE.getTransportWithSSLConfig(
               params.getHost(),
               params.getPort(),
               getNetworkTimeout(),
               params.getTrustStore(),
-              params.getTrustStorePwd());
+              params.getTrustStorePwd(),
+              params.getSslProtocol(),
+              params.getSslProviderClass());
     } else {
       transport =
           DeepCopyRpcTransportFactory.INSTANCE.getTransport(
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
index 1112caabd4e..4ae629e74b1 100644
--- 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
+++ 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
@@ -51,6 +51,8 @@ public class IoTDBConnectionParams {
   private boolean useSSL = false;
   private String trustStore;
   private String trustStorePwd;
+  private String sslProtocol = Config.DEFAULT_SSL_PROTOCOL;
+  private String sslProviderClass = Config.DEFAULT_SSL_PROVIDER_CLASS;
 
   private String sqlDialect = TREE;
 
@@ -184,6 +186,22 @@ public class IoTDBConnectionParams {
     this.trustStorePwd = trustStorePwd;
   }
 
+  public String getSslProtocol() {
+    return sslProtocol;
+  }
+
+  public void setSslProtocol(String sslProtocol) {
+    this.sslProtocol = sslProtocol;
+  }
+
+  public String getSslProviderClass() {
+    return sslProviderClass;
+  }
+
+  public void setSslProviderClass(String sslProviderClass) {
+    this.sslProviderClass = sslProviderClass;
+  }
+
   public String getSqlDialect() {
     return sqlDialect;
   }
diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
index 00e46cc340d..8bd394cf115 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
@@ -136,6 +136,12 @@ public class Utils {
     if (info.containsKey(Config.TRUST_STORE_PWD)) {
       params.setTrustStorePwd(info.getProperty(Config.TRUST_STORE_PWD));
     }
+    if (info.containsKey(Config.SSL_PROTOCOL)) {
+      params.setSslProtocol(info.getProperty(Config.SSL_PROTOCOL));
+    }
+    if (info.containsKey(Config.SSL_PROVIDER_CLASS)) {
+      params.setSslProviderClass(info.getProperty(Config.SSL_PROVIDER_CLASS));
+    }
     if (info.containsKey(Config.SQL_DIALECT)) {
       params.setSqlDialect(info.getProperty(Config.SQL_DIALECT));
     }
@@ -175,6 +181,8 @@ public class Utils {
         case Config.USE_SSL:
         case Config.TRUST_STORE:
         case Config.TRUST_STORE_PWD:
+        case Config.SSL_PROTOCOL:
+        case Config.SSL_PROVIDER_CLASS:
         case Config.VERSION:
         case Config.NETWORK_TIMEOUT:
         case Config.SQL_DIALECT:
diff --git 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
index 4c401b88017..32dd7a78a6d 100644
--- a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
+++ b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
@@ -159,4 +159,18 @@ public class UtilsTest {
     Utils.parseUrl("jdbc:iotdb://127.0.0.1:6667?rpc_compress=true", 
properties);
     assertTrue(Config.rpcThriftCompressionEnable);
   }
+
+  @Test
+  public void testParseSslConfig() throws IoTDBURLException {
+    Properties properties = new Properties();
+    IoTDBConnectionParams params =
+        Utils.parseUrl(
+            "jdbc:iotdb://127.0.0.1:6667?use_ssl=true&ssl_protocol=TLSv1.3"
+                + "&ssl_provider_class=com.example.ssl.Provider",
+            properties);
+
+    assertTrue(params.isUseSSL());
+    assertEquals("TLSv1.3", params.getSslProtocol());
+    assertEquals("com.example.ssl.Provider", params.getSslProviderClass());
+  }
 }
diff --git 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
index 22e104b6a58..58d8abbc60e 100644
--- 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
+++ 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/BaseRpcTransportFactory.java
@@ -84,8 +84,24 @@ public class BaseRpcTransportFactory extends 
TTransportFactory {
       String ip, int port, int timeout, String trustStore, String 
trustStorePwd)
       throws TTransportException {
     TSSLTransportFactory.TSSLTransportParameters params =
-        new TSSLTransportFactory.TSSLTransportParameters();
-    params.setTrustStore(trustStore, trustStorePwd);
+        RpcSslUtils.createTSSLTransportParameters();
+    RpcSslUtils.setTrustStore(params, trustStore, trustStorePwd);
+    TTransport transport = TSSLTransportFactory.getClientSocket(ip, port, 
timeout, params);
+    return inner.getTransport(transport);
+  }
+
+  public TTransport getTransportWithSSLConfig(
+      String ip,
+      int port,
+      int timeout,
+      String trustStore,
+      String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass)
+      throws TTransportException {
+    TSSLTransportFactory.TSSLTransportParameters params =
+        RpcSslUtils.createTSSLTransportParameters(sslProtocol, 
sslProviderClass, null);
+    RpcSslUtils.setTrustStore(params, trustStore, trustStorePwd, sslProtocol, 
sslProviderClass);
     TTransport transport = TSSLTransportFactory.getClientSocket(ip, port, 
timeout, params);
     return inner.getTransport(transport);
   }
@@ -100,10 +116,33 @@ public class BaseRpcTransportFactory extends 
TTransportFactory {
       String keyStorePwd)
       throws TTransportException {
     TSSLTransportFactory.TSSLTransportParameters params =
-        new TSSLTransportFactory.TSSLTransportParameters();
+        RpcSslUtils.createTSSLTransportParameters();
+    if (Files.exists(Paths.get(trustStore)) && 
Files.exists(Paths.get(keyStore))) {
+      RpcSslUtils.setTrustStore(params, trustStore, trustStorePwd);
+      RpcSslUtils.setKeyStore(params, keyStore, keyStorePwd);
+    } else {
+      throw new TTransportException(new 
IOException(RpcMessages.COULD_NOT_LOAD_KEYSTORE));
+    }
+    TTransport transport = TSSLTransportFactory.getClientSocket(ip, port, 
timeout, params);
+    return inner.getTransport(transport);
+  }
+
+  public TTransport getTransport(
+      String ip,
+      int port,
+      int timeout,
+      String trustStore,
+      String trustStorePwd,
+      String keyStore,
+      String keyStorePwd,
+      String sslProtocol,
+      String sslProviderClass)
+      throws TTransportException {
+    TSSLTransportFactory.TSSLTransportParameters params =
+        RpcSslUtils.createTSSLTransportParameters(sslProtocol, 
sslProviderClass, null);
     if (Files.exists(Paths.get(trustStore)) && 
Files.exists(Paths.get(keyStore))) {
-      params.setTrustStore(trustStore, trustStorePwd);
-      params.setKeyStore(keyStore, keyStorePwd);
+      RpcSslUtils.setTrustStore(params, trustStore, trustStorePwd, 
sslProtocol, sslProviderClass);
+      RpcSslUtils.setKeyStore(params, keyStore, keyStorePwd, sslProtocol, 
sslProviderClass);
     } else {
       throw new TTransportException(new 
IOException(RpcMessages.COULD_NOT_LOAD_KEYSTORE));
     }
diff --git 
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/RpcSslUtils.java 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/RpcSslUtils.java
new file mode 100644
index 00000000000..cfd0dca615e
--- /dev/null
+++ 
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/RpcSslUtils.java
@@ -0,0 +1,422 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.rpc;
+
+import org.apache.thrift.transport.TSSLTransportFactory;
+import org.apache.thrift.transport.TTransportException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.nio.file.AccessDeniedException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.stream.Stream;
+
+public final class RpcSslUtils {
+
+  private static final String DEFAULT_PROTOCOL = "TLS";
+  private static final String PKCS12_STORE_TYPE = "PKCS12";
+  private static final String JKS_STORE_TYPE = "JKS";
+
+  private static volatile SslConfig config = new SslConfig(DEFAULT_PROTOCOL, 
"", null);
+
+  private RpcSslUtils() {}
+
+  public static void configure(String protocol, String providerClass, String 
cipherSuites) {
+    config = newSslConfig(protocol, providerClass, cipherSuites);
+  }
+
+  public static void ensureProvider(String protocol, String providerClass)
+      throws TTransportException {
+    ensureProvider(newSslConfig(protocol, providerClass, null));
+  }
+
+  public static TSSLTransportFactory.TSSLTransportParameters 
createTSSLTransportParameters()
+      throws TTransportException {
+    SslConfig current = config;
+    ensureProvider(current);
+    return createTSSLTransportParameters(current);
+  }
+
+  public static TSSLTransportFactory.TSSLTransportParameters 
createTSSLTransportParameters(
+      String protocol, String providerClass, String cipherSuites) throws 
TTransportException {
+    SslConfig current = newSslConfig(protocol, providerClass, cipherSuites);
+    ensureProvider(current);
+    return createTSSLTransportParameters(current);
+  }
+
+  private static TSSLTransportFactory.TSSLTransportParameters 
createTSSLTransportParameters(
+      SslConfig current) {
+    return new TSSLTransportFactory.TSSLTransportParameters(current.protocol, 
current.cipherSuites);
+  }
+
+  public static void setKeyStore(
+      TSSLTransportFactory.TSSLTransportParameters params, String 
keyStorePath, String keyStorePwd)
+      throws TTransportException {
+    setKeyStore(params, keyStorePath, keyStorePwd, config);
+  }
+
+  public static void setKeyStore(
+      TSSLTransportFactory.TSSLTransportParameters params,
+      String keyStorePath,
+      String keyStorePwd,
+      String protocol,
+      String providerClass)
+      throws TTransportException {
+    setKeyStore(params, keyStorePath, keyStorePwd, newSslConfig(protocol, 
providerClass, null));
+  }
+
+  private static void setKeyStore(
+      TSSLTransportFactory.TSSLTransportParameters params,
+      String keyStorePath,
+      String keyStorePwd,
+      SslConfig current)
+      throws TTransportException {
+    try {
+      ensureProvider(current);
+      params.setKeyStore(
+          keyStorePath,
+          keyStorePwd,
+          KeyManagerFactory.getDefaultAlgorithm(),
+          detectStoreType(keyStorePath, keyStorePwd));
+    } catch (GeneralSecurityException | IOException e) {
+      throw new TTransportException(e);
+    }
+  }
+
+  public static void setTrustStore(
+      TSSLTransportFactory.TSSLTransportParameters params,
+      String trustStorePath,
+      String trustStorePwd)
+      throws TTransportException {
+    setTrustStore(params, trustStorePath, trustStorePwd, config);
+  }
+
+  public static void setTrustStore(
+      TSSLTransportFactory.TSSLTransportParameters params,
+      String trustStorePath,
+      String trustStorePwd,
+      String protocol,
+      String providerClass)
+      throws TTransportException {
+    setTrustStore(
+        params, trustStorePath, trustStorePwd, newSslConfig(protocol, 
providerClass, null));
+  }
+
+  private static void setTrustStore(
+      TSSLTransportFactory.TSSLTransportParameters params,
+      String trustStorePath,
+      String trustStorePwd,
+      SslConfig current)
+      throws TTransportException {
+    try {
+      ensureProvider(current);
+      params.setTrustStore(
+          trustStorePath,
+          trustStorePwd,
+          TrustManagerFactory.getDefaultAlgorithm(),
+          detectStoreType(trustStorePath, trustStorePwd));
+    } catch (GeneralSecurityException | IOException e) {
+      throw new TTransportException(e);
+    }
+  }
+
+  public static SSLContext createSSLContext(
+      String keyStorePath,
+      String keyStorePassword,
+      String trustStorePath,
+      String trustStorePassword)
+      throws GeneralSecurityException, IOException, TTransportException {
+    return createSSLContext(
+        keyStorePath, keyStorePassword, trustStorePath, trustStorePassword, 
config);
+  }
+
+  public static SSLContext createSSLContext(
+      String keyStorePath,
+      String keyStorePassword,
+      String trustStorePath,
+      String trustStorePassword,
+      String protocol,
+      String providerClass,
+      String cipherSuites)
+      throws GeneralSecurityException, IOException, TTransportException {
+    return createSSLContext(
+        keyStorePath,
+        keyStorePassword,
+        trustStorePath,
+        trustStorePassword,
+        newSslConfig(protocol, providerClass, cipherSuites));
+  }
+
+  private static SSLContext createSSLContext(
+      String keyStorePath,
+      String keyStorePassword,
+      String trustStorePath,
+      String trustStorePassword,
+      SslConfig current)
+      throws GeneralSecurityException, IOException, TTransportException {
+    ensureProvider(current);
+    SSLContext context = newSSLContext(current);
+    KeyManager[] keyManagers =
+        hasText(keyStorePath) ? loadKeyManagers(keyStorePath, 
keyStorePassword) : null;
+    TrustManager[] trustManagers =
+        hasText(trustStorePath) ? loadTrustManagers(trustStorePath, 
trustStorePassword) : null;
+    context.init(keyManagers, trustManagers, null);
+    return context;
+  }
+
+  public static KeyManager[] createKeyManagers(String keyStorePath, String 
keyStorePassword)
+      throws GeneralSecurityException, IOException, TTransportException {
+    ensureProvider(config);
+    return loadKeyManagers(keyStorePath, keyStorePassword);
+  }
+
+  public static TrustManager[] createTrustManagers(String trustStorePath, 
String trustStorePassword)
+      throws GeneralSecurityException, IOException, TTransportException {
+    ensureProvider(config);
+    return loadTrustManagers(trustStorePath, trustStorePassword);
+  }
+
+  public static String getProtocol() {
+    return config.protocol;
+  }
+
+  public static String[] getCipherSuites() {
+    SslConfig current = config;
+    return current.cipherSuites == null
+        ? null
+        : Arrays.copyOf(current.cipherSuites, current.cipherSuites.length);
+  }
+
+  public static boolean hasConfiguredProvider() {
+    return hasText(config.providerClass);
+  }
+
+  public static String getSSLContextProviderName() throws TTransportException {
+    ensureProvider(config);
+    try {
+      return newSSLContext(config).getProvider().getName();
+    } catch (GeneralSecurityException e) {
+      throw new TTransportException("Failed to initialize SSL context", e);
+    }
+  }
+
+  public static String[] getEnabledCipherSuites() throws TTransportException {
+    ensureProvider(config);
+    try {
+      SSLContext context = newSSLContext(config);
+      context.init(null, null, null);
+      SSLEngine engine = context.createSSLEngine();
+      return engine.getEnabledCipherSuites();
+    } catch (GeneralSecurityException e) {
+      throw new TTransportException("Failed to initialize SSL context", e);
+    }
+  }
+
+  public static void validateKeyStore(String keyStorePath, String 
keyStorePassword)
+      throws TTransportException {
+    validateStore(keyStorePath, keyStorePassword);
+  }
+
+  public static void validateTrustStore(String trustStorePath, String 
trustStorePassword)
+      throws TTransportException {
+    validateStore(trustStorePath, trustStorePassword);
+  }
+
+  private static KeyManager[] loadKeyManagers(String keyStorePath, String 
keyStorePassword)
+      throws GeneralSecurityException, IOException {
+    KeyStore keyStore = loadStore(keyStorePath, keyStorePassword);
+    KeyManagerFactory kmf = 
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+    kmf.init(keyStore, toPassword(keyStorePassword));
+    return kmf.getKeyManagers();
+  }
+
+  private static TrustManager[] loadTrustManagers(String trustStorePath, 
String trustStorePassword)
+      throws GeneralSecurityException, IOException {
+    KeyStore trustStore = loadStore(trustStorePath, trustStorePassword);
+    TrustManagerFactory tmf =
+        
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+    tmf.init(trustStore);
+    return tmf.getTrustManagers();
+  }
+
+  private static SSLContext newSSLContext(SslConfig current) throws 
GeneralSecurityException {
+    return SSLContext.getInstance(current.protocol);
+  }
+
+  private static String detectStoreType(String storePath, String storePassword)
+      throws GeneralSecurityException, IOException {
+    return loadStore(storePath, storePassword).getType();
+  }
+
+  private static KeyStore loadStore(String storePath, String storePassword)
+      throws GeneralSecurityException, IOException {
+    Exception lastException = null;
+    for (String storeType : storeTypeCandidates()) {
+      try {
+        return loadStore(storePath, storePassword, storeType);
+      } catch (AccessDeniedException | FileNotFoundException e) {
+        throw e;
+      } catch (GeneralSecurityException | IOException e) {
+        lastException = e;
+      }
+    }
+    if (lastException instanceof GeneralSecurityException) {
+      throw (GeneralSecurityException) lastException;
+    }
+    if (lastException instanceof IOException) {
+      throw (IOException) lastException;
+    }
+    throw new IOException("No supported keystore or truststore type is 
available");
+  }
+
+  private static KeyStore loadStore(String storePath, String storePassword, 
String storeType)
+      throws GeneralSecurityException, IOException {
+    KeyStore store = KeyStore.getInstance(storeType);
+    try (FileInputStream fis = new FileInputStream(storePath)) {
+      store.load(fis, toPassword(storePassword));
+    } catch (AccessDeniedException e) {
+      throw new AccessDeniedException("Failed to load keystore or truststore 
file");
+    } catch (FileNotFoundException e) {
+      throw new FileNotFoundException("keystore or truststore file not found: 
" + storePath);
+    }
+    return store;
+  }
+
+  private static void validateStore(String storePath, String storePassword)
+      throws TTransportException {
+    try {
+      ensureProvider(config);
+      KeyStore store = loadStore(storePath, storePassword);
+      Enumeration<String> aliases = store.aliases();
+      while (aliases.hasMoreElements()) {
+        X509Certificate cert = (X509Certificate) 
store.getCertificate(aliases.nextElement());
+        if (cert != null) {
+          cert.checkValidity();
+        }
+      }
+    } catch (Exception e) {
+      throw new TTransportException(e);
+    }
+  }
+
+  private static synchronized void ensureProvider(SslConfig current) throws 
TTransportException {
+    if (!hasText(current.providerClass)) {
+      return;
+    }
+    try {
+      String[] providerClassNames = 
splitProviderClasses(current.providerClass);
+      for (int i = providerClassNames.length - 1; i >= 0; i--) {
+        String providerClassName = providerClassNames[i];
+        Class<?> providerClass = Class.forName(providerClassName);
+        Constructor<?> constructor = providerClass.getDeclaredConstructor();
+        constructor.setAccessible(true);
+        Provider provider = (Provider) constructor.newInstance();
+        Provider firstProvider = Security.getProviders()[0];
+        if (!provider.getName().equals(firstProvider.getName())) {
+          Security.removeProvider(provider.getName());
+          Security.insertProviderAt(provider, 1);
+        }
+      }
+    } catch (Exception e) {
+      throw new TTransportException("Failed to initialize SSL provider", e);
+    }
+  }
+
+  private static char[] toPassword(String password) {
+    return password == null ? null : password.toCharArray();
+  }
+
+  private static String trimToDefault(String value, String defaultValue) {
+    String trimmed = trimToEmpty(value);
+    return trimmed.isEmpty() ? defaultValue : trimmed;
+  }
+
+  private static String trimToEmpty(String value) {
+    return value == null ? "" : value.trim();
+  }
+
+  private static boolean hasText(String value) {
+    return value != null && !value.trim().isEmpty();
+  }
+
+  private static String[] splitCipherSuites(String cipherSuites) {
+    if (!hasText(cipherSuites)) {
+      return null;
+    }
+    return splitCommaSeparated(cipherSuites);
+  }
+
+  private static String[] splitProviderClasses(String providerClasses) {
+    return splitCommaSeparated(providerClasses);
+  }
+
+  private static String[] splitCommaSeparated(String value) {
+    return Stream.of(value.split(","))
+        .map(String::trim)
+        .filter(s -> !s.isEmpty())
+        .toArray(String[]::new);
+  }
+
+  private static String[] storeTypeCandidates() {
+    return Stream.of(KeyStore.getDefaultType(), PKCS12_STORE_TYPE, 
JKS_STORE_TYPE)
+        .map(String::trim)
+        .map(s -> s.toUpperCase(Locale.ROOT))
+        .filter(s -> !s.isEmpty())
+        .distinct()
+        .toArray(String[]::new);
+  }
+
+  private static SslConfig newSslConfig(
+      String protocol, String providerClass, String cipherSuites) {
+    return new SslConfig(
+        trimToDefault(protocol, DEFAULT_PROTOCOL),
+        trimToEmpty(providerClass),
+        splitCipherSuites(cipherSuites));
+  }
+
+  private static final class SslConfig {
+    private final String protocol;
+    private final String providerClass;
+    private final String[] cipherSuites;
+
+    private SslConfig(String protocol, String providerClass, String[] 
cipherSuites) {
+      this.protocol = protocol;
+      this.providerClass = providerClass;
+      this.cipherSuites =
+          cipherSuites == null ? null : Arrays.copyOf(cipherSuites, 
cipherSuites.length);
+    }
+  }
+}
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/AbstractSessionBuilder.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/AbstractSessionBuilder.java
index f6132d8041f..2fe601f994d 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/AbstractSessionBuilder.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/AbstractSessionBuilder.java
@@ -62,6 +62,8 @@ public abstract class AbstractSessionBuilder {
   public boolean useSSL = false;
   public String trustStore;
   public String trustStorePwd;
+  public String sslProtocol = SessionConfig.DEFAULT_SSL_PROTOCOL;
+  public String sslProviderClass = SessionConfig.DEFAULT_SSL_PROVIDER_CLASS;
 
   // max retry count, if set to 0, means that we won't do any retry
   // we can use any available DataNodes(fetched in background thread if 
enableAutoFetch is true,
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/NodesSupplier.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/NodesSupplier.java
index d57844b4997..c6c2288b8b2 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/NodesSupplier.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/NodesSupplier.java
@@ -61,6 +61,8 @@ public class NodesSupplier implements INodeSupplier, Runnable 
{
   private final boolean useSSL;
   private final String trustStore;
   private final String trustStorePwd;
+  private final String sslProtocol;
+  private final String sslProviderClass;
   private final boolean enableRPCCompression;
   private final String userName;
 
@@ -95,6 +97,8 @@ public class NodesSupplier implements INodeSupplier, Runnable 
{
       boolean useSSL,
       String trustStore,
       String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass,
       boolean enableRPCCompression,
       String version) {
 
@@ -110,6 +114,8 @@ public class NodesSupplier implements INodeSupplier, 
Runnable {
             useSSL,
             trustStore,
             trustStorePwd,
+            sslProtocol,
+            sslProviderClass,
             enableRPCCompression,
             version);
 
@@ -132,6 +138,8 @@ public class NodesSupplier implements INodeSupplier, 
Runnable {
       boolean useSSL,
       String trustStore,
       String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass,
       boolean enableRPCCompression,
       String version) {
     this.availableNodes.addAll(new HashSet<>(endPointList));
@@ -140,6 +148,8 @@ public class NodesSupplier implements INodeSupplier, 
Runnable {
     this.useSSL = useSSL;
     this.trustStore = trustStore;
     this.trustStorePwd = trustStorePwd;
+    this.sslProtocol = sslProtocol;
+    this.sslProviderClass = sslProviderClass;
     this.enableRPCCompression = enableRPCCompression;
     this.zoneId = zoneId == null ? ZoneId.systemDefault() : zoneId;
     this.thriftDefaultBufferSize = thriftDefaultBufferSize;
@@ -188,6 +198,8 @@ public class NodesSupplier implements INodeSupplier, 
Runnable {
           useSSL,
           trustStore,
           trustStorePwd,
+          sslProtocol,
+          sslProviderClass,
           userName,
           password,
           enableRPCCompression,
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java
index b92df62f5ad..81798b046ba 100644
--- a/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java
+++ b/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java
@@ -133,6 +133,8 @@ public class Session implements ISession {
   protected boolean useSSL;
   protected String trustStore;
   protected String trustStorePwd;
+  protected String sslProtocol;
+  protected String sslProviderClass;
 
   /**
    * Timeout of query can be set by users. A negative number means using the 
default configuration
@@ -472,6 +474,8 @@ public class Session implements ISession {
     this.useSSL = builder.useSSL;
     this.trustStore = builder.trustStore;
     this.trustStorePwd = builder.trustStorePwd;
+    this.sslProtocol = builder.sslProtocol;
+    this.sslProviderClass = builder.sslProviderClass;
     this.enableAutoFetch = builder.enableAutoFetch;
     this.maxRetryCount = builder.maxRetryCount;
     this.retryIntervalInMs = builder.retryIntervalInMs;
@@ -541,6 +545,8 @@ public class Session implements ISession {
               useSSL,
               trustStore,
               trustStorePwd,
+              sslProtocol,
+              sslProviderClass,
               enableRPCCompaction,
               version.toString());
     } else {
@@ -4433,6 +4439,16 @@ public class Session implements ISession {
       return this;
     }
 
+    public Builder sslProtocol(String sslProtocol) {
+      this.sslProtocol = sslProtocol;
+      return this;
+    }
+
+    public Builder sslProviderClass(String sslProviderClass) {
+      this.sslProviderClass = sslProviderClass;
+      return this;
+    }
+
     public Session build() {
       if (nodeUrls != null
           && (!SessionConfig.DEFAULT_HOST.equals(host) || rpcPort != 
SessionConfig.DEFAULT_PORT)) {
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/SessionConnection.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/SessionConnection.java
index f6608d8fe4b..e12ccdcc0c5 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/SessionConnection.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/SessionConnection.java
@@ -151,7 +151,13 @@ public class SessionConnection {
     this.sqlDialect = sqlDialect;
     this.database = database;
     try {
-      init(endPoint, session.useSSL, session.trustStore, 
session.trustStorePwd);
+      init(
+          endPoint,
+          session.useSSL,
+          session.trustStore,
+          session.trustStorePwd,
+          session.sslProtocol,
+          session.sslProviderClass);
     } catch (StatementExecutionException e) {
       throw new IoTDBConnectionException(e.getMessage());
     } catch (IoTDBConnectionException e) {
@@ -179,7 +185,13 @@ public class SessionConnection {
     initClusterConn();
   }
 
-  private void init(TEndPoint endPoint, boolean useSSL, String trustStore, 
String trustStorePwd)
+  private void init(
+      TEndPoint endPoint,
+      boolean useSSL,
+      String trustStore,
+      String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass)
       throws IoTDBConnectionException, StatementExecutionException {
     
DeepCopyRpcTransportFactory.setDefaultBufferCapacity(session.thriftDefaultBufferSize);
     
DeepCopyRpcTransportFactory.setThriftMaxFrameSize(session.thriftMaxFrameSize);
@@ -189,12 +201,14 @@ public class SessionConnection {
       }
       if (useSSL) {
         transport =
-            DeepCopyRpcTransportFactory.INSTANCE.getTransport(
+            DeepCopyRpcTransportFactory.INSTANCE.getTransportWithSSLConfig(
                 endPoint.getIp(),
                 endPoint.getPort(),
                 session.connectionTimeoutInMs,
                 trustStore,
-                trustStorePwd);
+                trustStorePwd,
+                sslProtocol,
+                sslProviderClass);
       } else {
         transport =
             DeepCopyRpcTransportFactory.INSTANCE.getTransport(
@@ -262,7 +276,13 @@ public class SessionConnection {
     for (TEndPoint tEndPoint : endPointList) {
       try {
         session.defaultEndPoint = tEndPoint;
-        init(tEndPoint, session.useSSL, session.trustStore, 
session.trustStorePwd);
+        init(
+            tEndPoint,
+            session.useSSL,
+            session.trustStore,
+            session.trustStorePwd,
+            session.sslProtocol,
+            session.sslProviderClass);
       } catch (IoTDBConnectionException e) {
         if (!reconnect()) {
           logger.error(SessionMessages.CLUSTER_NO_NODES);
@@ -1079,7 +1099,13 @@ public class SessionConnection {
           }
           tryHostNum++;
           try {
-            init(endPoint, session.useSSL, session.trustStore, 
session.trustStorePwd);
+            init(
+                endPoint,
+                session.useSSL,
+                session.trustStore,
+                session.trustStorePwd,
+                session.sslProtocol,
+                session.sslProviderClass);
             connectedSuccess = true;
           } catch (IoTDBConnectionException e) {
             logger.warn(SessionMessages.NODE_DOWN_TRY_NEXT, endPoint);
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSessionBuilder.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSessionBuilder.java
index be53797165a..bc8ec1a1643 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSessionBuilder.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSessionBuilder.java
@@ -239,6 +239,30 @@ public class TableSessionBuilder extends 
AbstractSessionBuilder {
     return this;
   }
 
+  /**
+   * Sets the SSL protocol for secure connections.
+   *
+   * @param sslProtocol the SSL protocol.
+   * @return the current {@link TableSessionBuilder} instance.
+   * @defaultValue TLS
+   */
+  public TableSessionBuilder sslProtocol(String sslProtocol) {
+    this.sslProtocol = sslProtocol;
+    return this;
+  }
+
+  /**
+   * Sets the JSSE provider class for SSL connections.
+   *
+   * @param sslProviderClass the JSSE provider class.
+   * @return the current {@link TableSessionBuilder} instance.
+   * @defaultValue empty
+   */
+  public TableSessionBuilder sslProviderClass(String sslProviderClass) {
+    this.sslProviderClass = sslProviderClass;
+    return this;
+  }
+
   /**
    * Enables or disables rpc compression for the connection.
    *
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/ThriftConnection.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/ThriftConnection.java
index e3b9e8fc989..251ed3566cb 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/ThriftConnection.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/ThriftConnection.java
@@ -78,6 +78,8 @@ public class ThriftConnection {
       boolean useSSL,
       String trustStore,
       String trustStorePwd,
+      String sslProtocol,
+      String sslProviderClass,
       String username,
       String password,
       boolean enableRPCCompression,
@@ -89,12 +91,14 @@ public class ThriftConnection {
     try {
       if (useSSL) {
         transport =
-            DeepCopyRpcTransportFactory.INSTANCE.getTransport(
+            DeepCopyRpcTransportFactory.INSTANCE.getTransportWithSSLConfig(
                 endPoint.getIp(),
                 endPoint.getPort(),
                 connectionTimeoutInMs,
                 trustStore,
-                trustStorePwd);
+                trustStorePwd,
+                sslProtocol,
+                sslProviderClass);
       } else {
         transport =
             DeepCopyRpcTransportFactory.INSTANCE.getTransport(
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/SessionPool.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/SessionPool.java
index 3eaabe7f1fa..d7975f9b291 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/SessionPool.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/SessionPool.java
@@ -116,6 +116,11 @@ public class SessionPool implements ISessionPool {
   private String trustStore;
 
   private String trustStorePwd;
+
+  private String sslProtocol = SessionConfig.DEFAULT_SSL_PROTOCOL;
+
+  private String sslProviderClass = SessionConfig.DEFAULT_SSL_PROVIDER_CLASS;
+
   private ZoneId zoneId;
   // this field only take effect in write request, nothing to do with any 
other type requests,
   // like query, load and so on.
@@ -466,6 +471,8 @@ public class SessionPool implements ISessionPool {
     this.useSSL = useSSL;
     this.trustStore = trustStore;
     this.trustStorePwd = trustStorePwd;
+    this.sslProtocol = SessionConfig.DEFAULT_SSL_PROTOCOL;
+    this.sslProviderClass = SessionConfig.DEFAULT_SSL_PROVIDER_CLASS;
     initThreadPool();
     initAvailableNodes(Collections.singletonList(new TEndPoint(host, port)));
   }
@@ -536,6 +543,8 @@ public class SessionPool implements ISessionPool {
     this.useSSL = builder.useSSL;
     this.trustStore = builder.trustStore;
     this.trustStorePwd = builder.trustStorePwd;
+    this.sslProtocol = builder.sslProtocol;
+    this.sslProviderClass = builder.sslProviderClass;
     this.maxRetryCount = builder.maxRetryCount;
     this.retryIntervalInMs = builder.retryIntervalInMs;
     this.sqlDialect = builder.sqlDialect;
@@ -593,6 +602,8 @@ public class SessionPool implements ISessionPool {
               .useSSL(useSSL)
               .trustStore(trustStore)
               .trustStorePwd(trustStorePwd)
+              .sslProtocol(sslProtocol)
+              .sslProviderClass(sslProviderClass)
               .maxRetryCount(maxRetryCount)
               .retryIntervalInMs(retryIntervalInMs)
               .sqlDialect(sqlDialect)
@@ -618,6 +629,8 @@ public class SessionPool implements ISessionPool {
               .useSSL(useSSL)
               .trustStore(trustStore)
               .trustStorePwd(trustStorePwd)
+              .sslProtocol(sslProtocol)
+              .sslProviderClass(sslProviderClass)
               .maxRetryCount(maxRetryCount)
               .retryIntervalInMs(retryIntervalInMs)
               .sqlDialect(sqlDialect)
@@ -662,6 +675,8 @@ public class SessionPool implements ISessionPool {
             useSSL,
             trustStore,
             trustStorePwd,
+            sslProtocol,
+            sslProviderClass,
             enableThriftCompression,
             version.toString());
   }
@@ -3637,6 +3652,16 @@ public class SessionPool implements ISessionPool {
       return this;
     }
 
+    public Builder sslProtocol(String sslProtocol) {
+      this.sslProtocol = sslProtocol;
+      return this;
+    }
+
+    public Builder sslProviderClass(String sslProviderClass) {
+      this.sslProviderClass = sslProviderClass;
+      return this;
+    }
+
     public Builder host(String host) {
       this.host = host;
       return this;
diff --git 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/TableSessionPoolBuilder.java
 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/TableSessionPoolBuilder.java
index d5f52f3a8dc..ea02d8cf28c 100644
--- 
a/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/TableSessionPoolBuilder.java
+++ 
b/iotdb-client/session/src/main/java/org/apache/iotdb/session/pool/TableSessionPoolBuilder.java
@@ -281,6 +281,30 @@ public class TableSessionPoolBuilder extends 
AbstractSessionPoolBuilder {
     return this;
   }
 
+  /**
+   * Sets the SSL protocol for secure connections.
+   *
+   * @param sslProtocol the SSL protocol.
+   * @return the current {@link TableSessionPoolBuilder} instance.
+   * @defaultValue TLS
+   */
+  public TableSessionPoolBuilder sslProtocol(String sslProtocol) {
+    this.sslProtocol = sslProtocol;
+    return this;
+  }
+
+  /**
+   * Sets the JSSE provider class for SSL connections.
+   *
+   * @param sslProviderClass the JSSE provider class.
+   * @return the current {@link TableSessionPoolBuilder} instance.
+   * @defaultValue empty
+   */
+  public TableSessionPoolBuilder sslProviderClass(String sslProviderClass) {
+    this.sslProviderClass = sslProviderClass;
+    return this;
+  }
+
   /**
    * Builds and returns a configured {@link ITableSessionPool} instance.
    *
diff --git 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/utils/Utils.java
 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/utils/Utils.java
index 2c24ff12b6d..9e6cee14115 100644
--- 
a/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/utils/Utils.java
+++ 
b/iotdb-core/consensus/src/main/java/org/apache/iotdb/consensus/ratis/utils/Utils.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.consensus.common.Peer;
 import org.apache.iotdb.consensus.config.RatisConfig;
 import org.apache.iotdb.consensus.i18n.ConsensusMessages;
 import org.apache.iotdb.rpc.AutoScalingBufferWriteTransport;
+import org.apache.iotdb.rpc.RpcSslUtils;
 
 import org.apache.ratis.client.RaftClientConfigKeys;
 import org.apache.ratis.conf.Parameters;
@@ -53,19 +54,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.file.AccessDeniedException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.security.KeyStore;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -371,25 +366,10 @@ public class Utils {
       String keyStorePassword = config.getGrpc().getSslKeyStorePassword();
       String trustStorePath = config.getGrpc().getSslTrustStorePath();
       String trustStorePassword = config.getGrpc().getSslTrustStorePassword();
-      try (InputStream keyStoreStream = 
Files.newInputStream(Paths.get(keyStorePath));
-          InputStream trustStoreStream = 
Files.newInputStream(Paths.get(trustStorePath))) {
-        // === 1) create KeyManager ===
-        KeyStore keyStore = KeyStore.getInstance("JKS");
-        keyStore.load(keyStoreStream, keyStorePassword.toCharArray());
-
-        KeyManagerFactory kmf =
-            
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
-        kmf.init(keyStore, keyStorePassword.toCharArray());
-        KeyManager keyManager = kmf.getKeyManagers()[0];
-
-        // === 2) create TrustManager ===
-        KeyStore trustStore = KeyStore.getInstance("JKS");
-        trustStore.load(trustStoreStream, trustStorePassword.toCharArray());
-
-        TrustManagerFactory tmf =
-            
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
-        tmf.init(trustStore);
-        TrustManager originalTrustManager = tmf.getTrustManagers()[0];
+      try {
+        KeyManager keyManager = RpcSslUtils.createKeyManagers(keyStorePath, 
keyStorePassword)[0];
+        TrustManager originalTrustManager =
+            RpcSslUtils.createTrustManagers(trustStorePath, 
trustStorePassword)[0];
 
         // The self-signed certification may not set Subject Alternative Name 
(SAN)
         // Thrift with ssl didn't check it, but Grpc did.
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceConfig.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceConfig.java
index 64c0f65fe30..4e142a426b7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceConfig.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceConfig.java
@@ -45,6 +45,12 @@ public class IoTDBRestServiceConfig {
   /** ssl trust Store password. */
   private String trustStorePwd = "";
 
+  /** SSL protocol. */
+  private String sslProtocol = "";
+
+  /** SSL provider class. */
+  private String sslProviderClass = "";
+
   /** ssl timeout. */
   private int idleTimeoutInSeconds = 50000;
 
@@ -78,6 +84,22 @@ public class IoTDBRestServiceConfig {
     this.trustStorePwd = trustStorePwd;
   }
 
+  public String getSslProtocol() {
+    return sslProtocol;
+  }
+
+  public void setSslProtocol(String sslProtocol) {
+    this.sslProtocol = sslProtocol;
+  }
+
+  public String getSslProviderClass() {
+    return sslProviderClass;
+  }
+
+  public void setSslProviderClass(String sslProviderClass) {
+    this.sslProviderClass = sslProviderClass;
+  }
+
   public int getIdleTimeoutInSeconds() {
     return idleTimeoutInSeconds;
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
index 2e4ed0c28a6..c832d6cea62 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/rest/IoTDBRestServiceDescriptor.java
@@ -108,6 +108,9 @@ public class IoTDBRestServiceDescriptor {
     conf.setTrustStorePath(
         trimProperties.getProperty("trust_store_path", 
conf.getTrustStorePath()));
     conf.setTrustStorePwd(trimProperties.getProperty("trust_store_pwd", 
conf.getTrustStorePwd()));
+    conf.setSslProtocol(trimProperties.getProperty("ssl_protocol", 
conf.getSslProtocol()));
+    conf.setSslProviderClass(
+        trimProperties.getProperty("ssl_provider_class", 
conf.getSslProviderClass()));
     conf.setIdleTimeoutInSeconds(
         Integer.parseInt(
             trimProperties.getProperty(
diff --git 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
index 3b2d5ff5473..4b9156f02dd 100644
--- 
a/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
+++ 
b/iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template
@@ -474,6 +474,26 @@ trust_store_path=
 # Datatype: String
 trust_store_pwd=
 
+# SSL protocol used by SSL services.
+# effectiveMode: restart
+# Datatype: String
+# Privilege: SECURITY
+ssl_protocol=TLS
+
+# Optional JSSE provider class used by SSL. If set, the provider is registered 
with highest priority.
+# Multiple provider classes can be separated by commas.
+# effectiveMode: restart
+# Datatype: String
+# Privilege: SECURITY
+ssl_provider_class=
+
+# Comma-separated SSL cipher suites.
+# Leave empty to use the provider default.
+# effectiveMode: restart
+# Datatype: String
+# Privilege: SECURITY
+ssl_cipher_suites=
+
 ####################
 ### Connection Configuration
 ####################
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
index 6a8956e423b..73b286a30ab 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonConfig.java
@@ -467,6 +467,15 @@ public class CommonConfig {
   /** ssl trust Store password. */
   private String trustStorePwd = "";
 
+  /** SSL protocol. */
+  private String sslProtocol = "TLS";
+
+  /** SSL provider class. */
+  private String sslProviderClass = "";
+
+  /** SSL cipher suites. */
+  private String sslCipherSuites = "";
+
   private String userEncryptTokenHint = "not set yet";
 
   private boolean enforceStrongPassword = false;
@@ -2813,6 +2822,30 @@ public class CommonConfig {
     this.trustStorePwd = trustStorePwd;
   }
 
+  public String getSslProtocol() {
+    return sslProtocol;
+  }
+
+  public void setSslProtocol(String sslProtocol) {
+    this.sslProtocol = sslProtocol;
+  }
+
+  public String getSslProviderClass() {
+    return sslProviderClass;
+  }
+
+  public void setSslProviderClass(String sslProviderClass) {
+    this.sslProviderClass = sslProviderClass;
+  }
+
+  public String getSslCipherSuites() {
+    return sslCipherSuites;
+  }
+
+  public void setSslCipherSuites(String sslCipherSuites) {
+    this.sslCipherSuites = sslCipherSuites;
+  }
+
   public boolean isEnforceStrongPassword() {
     return enforceStrongPassword;
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
index 5cd954a09f7..aad31835a28 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/CommonDescriptor.java
@@ -24,6 +24,7 @@ import org.apache.iotdb.commons.pipe.config.PipeDescriptor;
 import org.apache.iotdb.commons.utils.CommonDateTimeUtils;
 import org.apache.iotdb.confignode.rpc.thrift.TAuditConfig;
 import org.apache.iotdb.confignode.rpc.thrift.TGlobalConfig;
+import org.apache.iotdb.rpc.RpcSslUtils;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -521,5 +522,16 @@ public class CommonDescriptor {
     config.setTrustStorePath(
         properties.getProperty("trust_store_path", 
config.getTrustStorePath()));
     config.setTrustStorePwd(properties.getProperty("trust_store_pwd", 
config.getTrustStorePwd()));
+    config.setSslProtocol(properties.getProperty("ssl_protocol", 
config.getSslProtocol()));
+    config.setSslProviderClass(
+        properties.getProperty("ssl_provider_class", 
config.getSslProviderClass()));
+    config.setSslCipherSuites(
+        properties.getProperty("ssl_cipher_suites", 
config.getSslCipherSuites()));
+    configureRpcSsl();
+  }
+
+  public void configureRpcSsl() {
+    RpcSslUtils.configure(
+        config.getSslProtocol(), config.getSslProviderClass(), 
config.getSslCipherSuites());
   }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
index 84361727a32..cd2716108ce 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/AbstractThriftServiceThread.java
@@ -24,6 +24,7 @@ import 
org.apache.iotdb.commons.concurrent.threadpool.WrappedThreadPoolExecutor;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.runtime.RPCServiceException;
 import org.apache.iotdb.commons.i18n.ServiceMessages;
+import org.apache.iotdb.rpc.RpcSslUtils;
 
 import org.apache.thrift.TBaseAsyncProcessor;
 import org.apache.thrift.TProcessor;
@@ -45,13 +46,7 @@ import org.apache.thrift.transport.TTransportFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.net.InetSocketAddress;
-import java.nio.file.AccessDeniedException;
-import java.security.KeyStore;
-import java.security.cert.X509Certificate;
-import java.util.Enumeration;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -184,13 +179,13 @@ public abstract class AbstractThriftServiceThread extends 
Thread {
     this.serviceName = serviceName;
 
     try {
-      validateCertificate(keyStorePath, keyStorePwd);
+      RpcSslUtils.validateKeyStore(keyStorePath, keyStorePwd);
       TSSLTransportFactory.TSSLTransportParameters params =
-          new TSSLTransportFactory.TSSLTransportParameters();
-      params.setKeyStore(keyStorePath, keyStorePwd);
+          RpcSslUtils.createTSSLTransportParameters();
+      RpcSslUtils.setKeyStore(params, keyStorePath, keyStorePwd);
       if (trustStorePath != null && !trustStorePath.isEmpty()) {
-        validateCertificate(trustStorePath, trustStorePwd);
-        params.setTrustStore(trustStorePath, trustStorePwd);
+        RpcSslUtils.validateTrustStore(trustStorePath, trustStorePwd);
+        RpcSslUtils.setTrustStore(params, trustStorePath, trustStorePwd);
         params.requireClientAuth(true);
       }
       InetSocketAddress socketAddress = new InetSocketAddress(bindAddress, 
port);
@@ -206,41 +201,6 @@ public abstract class AbstractThriftServiceThread extends 
Thread {
     }
   }
 
-  private static void validateCertificate(String keyStorePath, String 
keystorePassword)
-      throws TTransportException {
-    try {
-      KeyStore keystore = KeyStore.getInstance("JKS");
-      try (FileInputStream fis = new FileInputStream(keyStorePath)) {
-        keystore.load(fis, keystorePassword.toCharArray());
-      }
-
-      Enumeration<String> aliases = keystore.aliases();
-      while (aliases.hasMoreElements()) {
-        String currentAlias = aliases.nextElement();
-        checkCertificate(keystore, currentAlias);
-      }
-    } catch (AccessDeniedException e) {
-      throw new 
TTransportException(ServiceMessages.FAILED_TO_LOAD_KEYSTORE_OR_TRUSTSTORE);
-    } catch (FileNotFoundException e) {
-      throw new 
TTransportException(ServiceMessages.KEYSTORE_OR_TRUSTSTORE_NOT_FOUND);
-    } catch (Exception e) {
-      throw new TTransportException(e);
-    }
-  }
-
-  private static void checkCertificate(KeyStore keystore, String alias) throws 
Exception {
-    if (!keystore.containsAlias(alias)) {
-      return;
-    }
-
-    X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
-    if (cert == null) {
-      return;
-    }
-
-    cert.checkValidity();
-  }
-
   @SuppressWarnings("squid:S107")
   protected AbstractThriftServiceThread(
       TProcessor processor,

Reply via email to