cache default SSL root cert store
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index 886357f..0b53d63 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -102,8 +102,8 @@
     httpcli_ssl_destroy, httpcli_ssl_check_peer, httpcli_ssl_cmp};
 
 static grpc_security_status httpcli_ssl_channel_security_connector_create(
-    const char* pem_root_certs, const char* secure_peer_name,
-    grpc_channel_security_connector** sc) {
+    const char* pem_root_certs, const tsi_ssl_root_certs_store* root_store,
+    const char* secure_peer_name, grpc_channel_security_connector** sc) {
   tsi_result result = TSI_OK;
   grpc_httpcli_ssl_channel_security_connector* c;
 
@@ -124,6 +124,7 @@
   tsi_ssl_client_handshaker_options options;
   memset(&options, 0, sizeof(options));
   options.pem_root_certs = pem_root_certs;
+  options.root_store = root_store;
   result = tsi_create_ssl_client_handshaker_factory_with_options(
       &options, &c->handshaker_factory);
   if (result != TSI_OK) {
@@ -172,8 +173,11 @@
                           grpc_millis deadline,
                           void (*on_done)(void* arg, grpc_endpoint* endpoint)) {
   on_done_closure* c = static_cast<on_done_closure*>(gpr_malloc(sizeof(*c)));
-  const char* pem_root_certs = grpc_get_default_ssl_roots();
-  if (pem_root_certs == nullptr) {
+  const char* pem_root_certs =
+      grpc_core::DefaultSslRootStore::GetPemRootCerts();
+  const tsi_ssl_root_certs_store* root_store =
+      grpc_core::DefaultSslRootStore::GetRootStore();
+  if (root_store == nullptr) {
     gpr_log(GPR_ERROR, "Could not get default pem root certs.");
     on_done(arg, nullptr);
     gpr_free(c);
@@ -183,7 +187,7 @@
   c->arg = arg;
   grpc_channel_security_connector* sc = nullptr;
   GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
-                 pem_root_certs, host, &sc) == GRPC_SECURITY_OK);
+                 pem_root_certs, root_store, host, &sc) == GRPC_SECURITY_OK);
   grpc_arg channel_arg = grpc_security_connector_to_arg(&sc->base);
   grpc_channel_args args = {1, &channel_arg};
   c->handshake_mgr = grpc_handshake_manager_create();
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index cbe77d5..3967112 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -965,63 +965,6 @@
 static grpc_security_connector_vtable ssl_server_vtable = {
     ssl_server_destroy, ssl_server_check_peer, ssl_server_cmp};
 
-/* returns a NULL terminated slice. */
-static grpc_slice compute_default_pem_root_certs_once(void) {
-  grpc_slice result = grpc_empty_slice();
-
-  /* First try to load the roots from the environment. */
-  char* default_root_certs_path =
-      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
-  if (default_root_certs_path != nullptr) {
-    GRPC_LOG_IF_ERROR("load_file",
-                      grpc_load_file(default_root_certs_path, 1, &result));
-    gpr_free(default_root_certs_path);
-  }
-
-  /* Try overridden roots if needed. */
-  grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
-  if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) {
-    char* pem_root_certs = nullptr;
-    ovrd_res = ssl_roots_override_cb(&pem_root_certs);
-    if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) {
-      GPR_ASSERT(pem_root_certs != nullptr);
-      result = grpc_slice_from_copied_buffer(
-          pem_root_certs,
-          strlen(pem_root_certs) + 1);  // NULL terminator.
-    }
-    gpr_free(pem_root_certs);
-  }
-
-  /* Fall back to installed certs if needed. */
-  if (GRPC_SLICE_IS_EMPTY(result) &&
-      ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
-    GRPC_LOG_IF_ERROR("load_file",
-                      grpc_load_file(installed_roots_path, 1, &result));
-  }
-  return result;
-}
-
-static grpc_slice default_pem_root_certs;
-
-static void init_default_pem_root_certs(void) {
-  default_pem_root_certs = compute_default_pem_root_certs_once();
-}
-
-grpc_slice grpc_get_default_ssl_roots_for_testing(void) {
-  return compute_default_pem_root_certs_once();
-}
-
-const char* grpc_get_default_ssl_roots(void) {
-  /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
-     loading all the roots once for the lifetime of the process. */
-  static gpr_once once = GPR_ONCE_INIT;
-  gpr_once_init(&once, init_default_pem_root_certs);
-  return GRPC_SLICE_IS_EMPTY(default_pem_root_certs)
-             ? nullptr
-             : reinterpret_cast<const char*>
-                   GRPC_SLICE_START_PTR(default_pem_root_certs);
-}
-
 grpc_security_status grpc_ssl_channel_security_connector_create(
     grpc_channel_credentials* channel_creds,
     grpc_call_credentials* request_metadata_creds,
@@ -1043,7 +986,9 @@
     goto error;
   }
   if (config->pem_root_certs == nullptr) {
-    options.pem_root_certs = grpc_get_default_ssl_roots();
+    // Use default root certificates.
+    options.pem_root_certs = grpc_core::DefaultSslRootStore::GetPemRootCerts();
+    options.root_store = grpc_core::DefaultSslRootStore::GetRootStore();
     if (options.pem_root_certs == nullptr) {
       gpr_log(GPR_ERROR, "Could not get default pem root certs.");
       goto error;
@@ -1051,7 +996,6 @@
   } else {
     options.pem_root_certs = config->pem_root_certs;
   }
-
   c = static_cast<grpc_ssl_channel_security_connector*>(
       gpr_zalloc(sizeof(grpc_ssl_channel_security_connector)));
 
@@ -1157,3 +1101,79 @@
   }
   return retval;
 }
+
+namespace grpc_core {
+
+tsi_ssl_root_certs_store* DefaultSslRootStore::default_root_store_;
+grpc_slice DefaultSslRootStore::default_pem_root_certs_;
+
+const tsi_ssl_root_certs_store* DefaultSslRootStore::GetRootStore() {
+  InitRootStore();
+  return default_root_store_;
+}
+
+const char* DefaultSslRootStore::GetPemRootCerts() {
+  InitRootStore();
+  return GRPC_SLICE_IS_EMPTY(default_pem_root_certs_)
+             ? nullptr
+             : reinterpret_cast<const char*>
+                   GRPC_SLICE_START_PTR(default_pem_root_certs_);
+}
+
+void DefaultSslRootStore::Initialize() {
+  default_root_store_ = nullptr;
+  default_pem_root_certs_ = grpc_empty_slice();
+}
+
+void DefaultSslRootStore::Destroy() {
+  tsi_ssl_root_certs_store_destroy(default_root_store_);
+  grpc_slice_unref_internal(default_pem_root_certs_);
+}
+
+grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
+  grpc_slice result = grpc_empty_slice();
+  // First try to load the roots from the environment.
+  char* default_root_certs_path =
+      gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
+  if (default_root_certs_path != nullptr) {
+    GRPC_LOG_IF_ERROR("load_file",
+                      grpc_load_file(default_root_certs_path, 1, &result));
+    gpr_free(default_root_certs_path);
+  }
+  // Try overridden roots if needed.
+  grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL;
+  if (GRPC_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != nullptr) {
+    char* pem_root_certs = nullptr;
+    ovrd_res = ssl_roots_override_cb(&pem_root_certs);
+    if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) {
+      GPR_ASSERT(pem_root_certs != nullptr);
+      result = grpc_slice_from_copied_buffer(
+          pem_root_certs,
+          strlen(pem_root_certs) + 1);  // nullptr terminator.
+    }
+    gpr_free(pem_root_certs);
+  }
+  // Fall back to installed certs if needed.
+  if (GRPC_SLICE_IS_EMPTY(result) &&
+      ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) {
+    GRPC_LOG_IF_ERROR("load_file",
+                      grpc_load_file(installed_roots_path, 1, &result));
+  }
+  return result;
+}
+
+void DefaultSslRootStore::InitRootStore() {
+  static gpr_once once = GPR_ONCE_INIT;
+  gpr_once_init(&once, DefaultSslRootStore::InitRootStoreOnce);
+}
+
+void DefaultSslRootStore::InitRootStoreOnce() {
+  default_pem_root_certs_ = ComputePemRootCerts();
+  if (!GRPC_SLICE_IS_EMPTY(default_pem_root_certs_)) {
+    default_root_store_ =
+        tsi_ssl_root_certs_store_create(reinterpret_cast<const char*>(
+            GRPC_SLICE_START_PTR(default_pem_root_certs_)));
+  }
+}
+
+}  // namespace grpc_core
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index dc847d9..5d3d1e0 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -216,12 +216,6 @@
     tsi_ssl_session_cache* ssl_session_cache,
     grpc_channel_security_connector** sc);
 
-/* Gets the default ssl roots. Returns NULL if not found. */
-const char* grpc_get_default_ssl_roots(void);
-
-/* Exposed for TESTING ONLY!. */
-grpc_slice grpc_get_default_ssl_roots_for_testing(void);
-
 /* Config for ssl servers. */
 typedef struct {
   tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs;
@@ -250,4 +244,49 @@
     const grpc_auth_context* auth_context);
 void tsi_shallow_peer_destruct(tsi_peer* peer);
 
+/* --- Default SSL Root Store. --- */
+namespace grpc_core {
+
+// The class implements default SSL root store.
+class DefaultSslRootStore {
+ public:
+  // Gets the default SSL root store. Returns nullptr if not found.
+  static const tsi_ssl_root_certs_store* GetRootStore();
+
+  // Gets the default PEM root certificate.
+  static const char* GetPemRootCerts();
+
+  // Initializes the SSL root store's underlying data structure. It does not
+  // load default SSL root certificates. Should only be called by
+  // grpc_security_init().
+  static void Initialize();
+
+  // Destroys the default SSL root store. Should only be called by
+  // grpc_security_shutdown().
+  static void Destroy();
+
+ protected:
+  // Returns default PEM root certificates in nullptr terminated grpc_slice.
+  // This function is protected instead of private, so that it can be tested.
+  static grpc_slice ComputePemRootCerts();
+
+ private:
+  // Construct me not!
+  DefaultSslRootStore();
+
+  // Initialization of default SSL root store.
+  static void InitRootStore();
+
+  // One-time initialization of default SSL root store.
+  static void InitRootStoreOnce();
+
+  // SSL root store in tsi_ssl_root_certs_store object.
+  static tsi_ssl_root_certs_store* default_root_store_;
+
+  // Default PEM root certificates.
+  static grpc_slice default_pem_root_certs_;
+};
+
+}  // namespace grpc_core
+
 #endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_SECURITY_CONNECTOR_H */
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index bd436d6..52e0ee1 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -172,6 +172,7 @@
           }
         }
       }
+      grpc_security_shutdown();
       grpc_iomgr_shutdown();
       gpr_timers_global_destroy();
       grpc_tracer_shutdown();
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
index 9353208..d8282b4 100644
--- a/src/core/lib/surface/init.h
+++ b/src/core/lib/surface/init.h
@@ -22,6 +22,7 @@
 void grpc_register_security_filters(void);
 void grpc_security_pre_init(void);
 void grpc_security_init(void);
+void grpc_security_shutdown(void);
 int grpc_is_initialized(void);
 
 #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc
index 78e983e..3e4f1a8 100644
--- a/src/core/lib/surface/init_secure.cc
+++ b/src/core/lib/surface/init_secure.cc
@@ -75,4 +75,9 @@
                                    maybe_prepend_server_auth_filter, nullptr);
 }
 
-void grpc_security_init() { grpc_security_register_handshaker_factories(); }
+void grpc_security_init() {
+  grpc_security_register_handshaker_factories();
+  grpc_core::DefaultSslRootStore::Initialize();
+}
+
+void grpc_security_shutdown() { grpc_core::DefaultSslRootStore::Destroy(); }
diff --git a/src/core/lib/surface/init_unsecure.cc b/src/core/lib/surface/init_unsecure.cc
index 2b3bc64..1c8d07b 100644
--- a/src/core/lib/surface/init_unsecure.cc
+++ b/src/core/lib/surface/init_unsecure.cc
@@ -25,3 +25,5 @@
 void grpc_register_security_filters(void) {}
 
 void grpc_security_init(void) {}
+
+void grpc_security_shutdown(void) {}
diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc
index 0fc2926..0ba6587 100644
--- a/src/core/tsi/ssl_transport_security.cc
+++ b/src/core/tsi/ssl_transport_security.cc
@@ -71,6 +71,10 @@
 
 /* --- Structure definitions. ---*/
 
+struct tsi_ssl_root_certs_store {
+  X509_STORE* store;
+};
+
 struct tsi_ssl_handshaker_factory {
   const tsi_ssl_handshaker_factory_vtable* vtable;
   gpr_refcount refcount;
@@ -553,21 +557,18 @@
 
 /* Loads in-memory PEM verification certs into the SSL context and optionally
    returns the verification cert names (root_names can be NULL). */
-static tsi_result ssl_ctx_load_verification_certs(SSL_CTX* context,
-                                                  const char* pem_roots,
-                                                  size_t pem_roots_size,
-                                                  STACK_OF(X509_NAME) *
-                                                      *root_names) {
+static tsi_result x509_store_load_certs(X509_STORE* cert_store,
+                                        const char* pem_roots,
+                                        size_t pem_roots_size,
+                                        STACK_OF(X509_NAME) * *root_names) {
   tsi_result result = TSI_OK;
   size_t num_roots = 0;
   X509* root = nullptr;
   X509_NAME* root_name = nullptr;
   BIO* pem;
-  X509_STORE* root_store;
   GPR_ASSERT(pem_roots_size <= INT_MAX);
   pem = BIO_new_mem_buf((void*)pem_roots, static_cast<int>(pem_roots_size));
-  root_store = SSL_CTX_get_cert_store(context);
-  if (root_store == nullptr) return TSI_INVALID_ARGUMENT;
+  if (cert_store == nullptr) return TSI_INVALID_ARGUMENT;
   if (pem == nullptr) return TSI_OUT_OF_RESOURCES;
   if (root_names != nullptr) {
     *root_names = sk_X509_NAME_new_null();
@@ -595,7 +596,7 @@
       sk_X509_NAME_push(*root_names, root_name);
       root_name = nullptr;
     }
-    if (!X509_STORE_add_cert(root_store, root)) {
+    if (!X509_STORE_add_cert(cert_store, root)) {
       gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
       result = TSI_INTERNAL_ERROR;
       break;
@@ -621,6 +622,16 @@
   return result;
 }
 
+static tsi_result ssl_ctx_load_verification_certs(SSL_CTX* context,
+                                                  const char* pem_roots,
+                                                  size_t pem_roots_size,
+                                                  STACK_OF(X509_NAME) *
+                                                      *root_name) {
+  X509_STORE* cert_store = SSL_CTX_get_cert_store(context);
+  return x509_store_load_certs(cert_store, pem_roots, pem_roots_size,
+                               root_name);
+}
+
 /* Populates the SSL context with a private key and a cert chain, and sets the
    cipher list and the ephemeral ECDH key. */
 static tsi_result populate_ssl_context(
@@ -730,6 +741,43 @@
   return 1;
 }
 
+/* --- tsi_ssl_root_certs_store methods implementation. ---*/
+
+tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
+    const char* pem_roots) {
+  if (pem_roots == nullptr) {
+    gpr_log(GPR_ERROR, "The root certificates are empty.");
+    return nullptr;
+  }
+  tsi_ssl_root_certs_store* root_store = static_cast<tsi_ssl_root_certs_store*>(
+      gpr_zalloc(sizeof(tsi_ssl_root_certs_store)));
+  if (root_store == nullptr) {
+    gpr_log(GPR_ERROR, "Could not allocate buffer for ssl_root_certs_store.");
+    return nullptr;
+  }
+  root_store->store = X509_STORE_new();
+  if (root_store->store == nullptr) {
+    gpr_log(GPR_ERROR, "Could not allocate buffer for X509_STORE.");
+    gpr_free(root_store);
+    return nullptr;
+  }
+  tsi_result result = x509_store_load_certs(root_store->store, pem_roots,
+                                            strlen(pem_roots), nullptr);
+  if (result != TSI_OK) {
+    gpr_log(GPR_ERROR, "Could not load root certificates.");
+    X509_STORE_free(root_store->store);
+    gpr_free(root_store);
+    return nullptr;
+  }
+  return root_store;
+}
+
+void tsi_ssl_root_certs_store_destroy(tsi_ssl_root_certs_store* self) {
+  if (self == nullptr) return;
+  X509_STORE_free(self->store);
+  gpr_free(self);
+}
+
 /* --- tsi_ssl_session_cache methods implementation. ---*/
 
 tsi_ssl_session_cache* tsi_ssl_session_cache_create_lru(size_t capacity) {
@@ -1468,7 +1516,9 @@
 
   if (factory == nullptr) return TSI_INVALID_ARGUMENT;
   *factory = nullptr;
-  if (options->pem_root_certs == nullptr) return TSI_INVALID_ARGUMENT;
+  if (options->pem_root_certs == nullptr && options->root_store == nullptr) {
+    return TSI_INVALID_ARGUMENT;
+  }
 
   ssl_context = SSL_CTX_new(TLSv1_2_method());
   if (ssl_context == nullptr) {
@@ -1480,9 +1530,7 @@
       gpr_zalloc(sizeof(*impl)));
   tsi_ssl_handshaker_factory_init(&impl->base);
   impl->base.vtable = &client_handshaker_factory_vtable;
-
   impl->ssl_context = ssl_context;
-
   if (options->session_cache != nullptr) {
     // Unref is called manually on factory destruction.
     impl->session_cache =
@@ -1498,12 +1546,22 @@
     result = populate_ssl_context(ssl_context, options->pem_key_cert_pair,
                                   options->cipher_suites);
     if (result != TSI_OK) break;
-    result = ssl_ctx_load_verification_certs(
-        ssl_context, options->pem_root_certs, strlen(options->pem_root_certs),
-        nullptr);
-    if (result != TSI_OK) {
-      gpr_log(GPR_ERROR, "Cannot load server root certificates.");
-      break;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
+    // X509_STORE_up_ref is only available since OpenSSL 1.1.
+    if (options->root_store != nullptr) {
+      X509_STORE_up_ref(options->root_store->store);
+      SSL_CTX_set_cert_store(ssl_context, options->root_store->store);
+    }
+#endif
+    if (OPENSSL_VERSION_NUMBER < 0x10100000 || options->root_store == nullptr) {
+      result = ssl_ctx_load_verification_certs(
+          ssl_context, options->pem_root_certs, strlen(options->pem_root_certs),
+          nullptr);
+      if (result != TSI_OK) {
+        gpr_log(GPR_ERROR, "Cannot load server root certificates.");
+        break;
+      }
     }
 
     if (options->num_alpn_protocols != 0) {
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
index 29d209b..cabf583 100644
--- a/src/core/tsi/ssl_transport_security.h
+++ b/src/core/tsi/ssl_transport_security.h
@@ -36,6 +36,20 @@
 
 #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
 
+/* --- tsi_ssl_root_certs_store object ---
+
+   This object stores SSL root certificates. It can be shared by multiple SSL
+   context. */
+typedef struct tsi_ssl_root_certs_store tsi_ssl_root_certs_store;
+
+/* Given a NULL-terminated string containing the PEM encoding of the root
+   certificates, creates a tsi_ssl_root_certs_store object. */
+tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
+    const char* pem_roots);
+
+/* Destroys the tsi_ssl_root_certs_store object. */
+void tsi_ssl_root_certs_store_destroy(tsi_ssl_root_certs_store* self);
+
 /* --- tsi_ssl_session_cache object ---
 
    Cache for SSL sessions for sessions resumption.  */
@@ -70,13 +84,13 @@
   const char* cert_chain;
 } tsi_ssl_pem_key_cert_pair;
 
-/* Creates a client handshaker factory.
+/* TO BE DEPRECATED.
+   Creates a client handshaker factory.
    - pem_key_cert_pair is a pointer to the object containing client's private
      key and certificate chain. This parameter can be NULL if the client does
      not have such a key/cert pair.
    - pem_roots_cert is the NULL-terminated string containing the PEM encoding of
-     the client root certificates. This parameter may be NULL if the server does
-     not want the client to be authenticated with SSL.
+     the server root certificates.
    - cipher_suites contains an optional list of the ciphers that the client
      supports. The format of this string is described in:
      https://www.openssl.org/docs/apps/ciphers.html.
@@ -103,9 +117,13 @@
      not have such a key/cert pair. */
   const tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
   /* pem_roots_cert is the NULL-terminated string containing the PEM encoding of
-     the client root certificates. This parameter may be NULL if the server does
-     not want the client to be authenticated with SSL. */
+     the client root certificates. */
   const char* pem_root_certs;
+  /* root_store is a pointer to the ssl_root_certs_store object. If root_store
+    is not nullptr and SSL implementation permits, root_store will be used as
+    root certificates. Otherwise, pem_roots_cert will be used to load server
+    root certificates. */
+  const tsi_ssl_root_certs_store* root_store;
   /* cipher_suites contains an optional list of the ciphers that the client
      supports. The format of this string is described in:
      https://www.openssl.org/docs/apps/ciphers.html.
@@ -160,12 +178,14 @@
 typedef struct tsi_ssl_server_handshaker_factory
     tsi_ssl_server_handshaker_factory;
 
-/* Creates a server handshaker factory.
+/* TO BE DEPRECATED.
+   Creates a server handshaker factory.
    - pem_key_cert_pairs is an array private key / certificate chains of the
      server.
    - num_key_cert_pairs is the number of items in the pem_key_cert_pairs array.
    - pem_root_certs is the NULL-terminated string containing the PEM encoding
-     of the server root certificates.
+     of the client root certificates. This parameter may be NULL if the server
+     does not want the client to be authenticated with SSL.
    - cipher_suites contains an optional list of the ciphers that the server
      supports. The format of this string is described in:
      https://www.openssl.org/docs/apps/ciphers.html.
@@ -187,7 +207,8 @@
     const char** alpn_protocols, uint16_t num_alpn_protocols,
     tsi_ssl_server_handshaker_factory** factory);
 
-/* Same as tsi_create_ssl_server_handshaker_factory method except uses
+/* TO BE DEPRECATED.
+   Same as tsi_create_ssl_server_handshaker_factory method except uses
    tsi_client_certificate_request_type to support more ways to handle client
    certificate authentication.
    - client_certificate_request, if set to non-zero will force the client to
@@ -208,7 +229,8 @@
      array. */
   size_t num_key_cert_pairs;
   /* pem_root_certs is the NULL-terminated string containing the PEM encoding
-     of the server root certificates. */
+     of the server root certificates. This parameter may be NULL if the server
+     does not want the client to be authenticated with SSL. */
   const char* pem_client_root_certs;
   /* client_certificate_request, if set to non-zero will force the client to
      authenticate with an SSL cert. Note that this option is ignored if
diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc
index ed3849b..f03f4cc 100644
--- a/test/core/security/security_connector_test.cc
+++ b/test/core/security/security_connector_test.cc
@@ -340,6 +340,21 @@
   return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
 }
 
+namespace grpc_core {
+namespace {
+
+class TestDefafaultSllRootStore : public DefaultSslRootStore {
+ public:
+  static grpc_slice ComputePemRootCertsForTesting() {
+    return ComputePemRootCerts();
+  }
+};
+
+}  // namespace
+}  // namespace grpc_core
+
+// TODO: Convert this test to C++ test when security_connector implementation
+// is converted to C++.
 static void test_default_ssl_roots(void) {
   const char* roots_for_env_var = "roots for env var";
 
@@ -353,7 +368,8 @@
      value. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
   grpc_set_ssl_roots_override_callback(override_roots_success);
-  grpc_slice roots = grpc_get_default_ssl_roots_for_testing();
+  grpc_slice roots =
+      grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
   char* roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
@@ -362,7 +378,7 @@
   /* Now let's set the env var: We should get the contents pointed value
      instead. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path);
-  roots = grpc_get_default_ssl_roots_for_testing();
+  roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
   roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
@@ -371,7 +387,7 @@
   /* Now reset the env var. We should fall back to the value overridden using
      the api. */
   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
-  roots = grpc_get_default_ssl_roots_for_testing();
+  roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
   roots_contents = grpc_slice_to_c_string(roots);
   grpc_slice_unref(roots);
   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
@@ -380,8 +396,11 @@
   /* Now setup a permanent failure for the overridden roots and we should get
      an empty slice. */
   grpc_set_ssl_roots_override_callback(override_roots_permanent_failure);
-  roots = grpc_get_default_ssl_roots_for_testing();
+  roots = grpc_core::TestDefafaultSllRootStore::ComputePemRootCertsForTesting();
   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots));
+  const tsi_ssl_root_certs_store* root_store =
+      grpc_core::TestDefafaultSllRootStore::GetRootStore();
+  GPR_ASSERT(root_store == nullptr);
 
   /* Cleanup. */
   remove(roots_env_var_file_path);
diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc
index 0878c57..88f1abc 100644
--- a/test/core/tsi/ssl_transport_security_test.cc
+++ b/test/core/tsi/ssl_transport_security_test.cc
@@ -61,7 +61,9 @@
 typedef struct ssl_key_cert_lib {
   bool use_bad_server_cert;
   bool use_bad_client_cert;
+  bool use_root_store;
   char* root_cert;
+  tsi_ssl_root_certs_store* root_store;
   tsi_ssl_pem_key_cert_pair* server_pem_key_cert_pairs;
   tsi_ssl_pem_key_cert_pair* bad_server_pem_key_cert_pairs;
   tsi_ssl_pem_key_cert_pair client_pem_key_cert_pair;
@@ -108,6 +110,8 @@
     client_options.alpn_protocols = alpn_lib->client_alpn_protocols;
     client_options.num_alpn_protocols = alpn_lib->num_client_alpn_protocols;
   }
+  client_options.root_store =
+      key_cert_lib->use_root_store ? key_cert_lib->root_store : nullptr;
   if (ssl_fixture->session_cache != nullptr) {
     client_options.session_cache = ssl_fixture->session_cache;
   }
@@ -345,6 +349,7 @@
   ssl_test_pem_key_cert_pair_destroy(
       key_cert_lib->bad_client_pem_key_cert_pair);
   gpr_free(key_cert_lib->root_cert);
+  tsi_ssl_root_certs_store_destroy(key_cert_lib->root_store);
   gpr_free(key_cert_lib);
   if (ssl_fixture->session_cache != nullptr) {
     tsi_ssl_session_cache_unref(ssl_fixture->session_cache);
@@ -384,6 +389,7 @@
       static_cast<ssl_key_cert_lib*>(gpr_zalloc(sizeof(*key_cert_lib)));
   key_cert_lib->use_bad_server_cert = false;
   key_cert_lib->use_bad_client_cert = false;
+  key_cert_lib->use_root_store = false;
   key_cert_lib->server_num_key_cert_pairs =
       SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM;
   key_cert_lib->bad_server_num_key_cert_pairs =
@@ -417,6 +423,9 @@
   key_cert_lib->bad_client_pem_key_cert_pair.cert_chain =
       load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.pem");
   key_cert_lib->root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem");
+  key_cert_lib->root_store =
+      tsi_ssl_root_certs_store_create(key_cert_lib->root_cert);
+  GPR_ASSERT(key_cert_lib->root_store != nullptr);
   ssl_fixture->key_cert_lib = key_cert_lib;
   /* Create ssl_alpn_lib. */
   ssl_alpn_lib* alpn_lib =
@@ -462,6 +471,15 @@
   tsi_test_fixture_destroy(fixture);
 }
 
+void ssl_tsi_test_do_handshake_with_root_store() {
+  tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
+  ssl_tsi_test_fixture* ssl_fixture =
+      reinterpret_cast<ssl_tsi_test_fixture*>(fixture);
+  ssl_fixture->key_cert_lib->use_root_store = true;
+  tsi_test_do_handshake(fixture);
+  tsi_test_fixture_destroy(fixture);
+}
+
 void ssl_tsi_test_do_handshake_with_client_authentication() {
   tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
   ssl_tsi_test_fixture* ssl_fixture =
@@ -471,6 +489,16 @@
   tsi_test_fixture_destroy(fixture);
 }
 
+void ssl_tsi_test_do_handshake_with_client_authentication_and_root_store() {
+  tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
+  ssl_tsi_test_fixture* ssl_fixture =
+      reinterpret_cast<ssl_tsi_test_fixture*>(fixture);
+  ssl_fixture->force_client_auth = true;
+  ssl_fixture->key_cert_lib->use_root_store = true;
+  tsi_test_do_handshake(fixture);
+  tsi_test_fixture_destroy(fixture);
+}
+
 void ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain() {
   /* server1 cert contains "waterzooi.test.google.be" in SAN. */
   tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
@@ -727,9 +755,11 @@
   const char* cert_chain = "This is not a valid PEM file.";
 
   tsi_ssl_client_handshaker_factory* client_handshaker_factory;
-  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory(
-                 nullptr, cert_chain, nullptr, nullptr, 0,
-                 &client_handshaker_factory) == TSI_INVALID_ARGUMENT);
+  tsi_ssl_client_handshaker_options options;
+  memset(&options, 0, sizeof(options));
+  options.pem_root_certs = cert_chain;
+  GPR_ASSERT(tsi_create_ssl_client_handshaker_factory_with_options(
+                 &options, &client_handshaker_factory) == TSI_INVALID_ARGUMENT);
   tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory);
 }
 
@@ -746,7 +776,9 @@
   ssl_tsi_test_do_handshake_tiny_handshake_buffer();
   ssl_tsi_test_do_handshake_small_handshake_buffer();
   ssl_tsi_test_do_handshake();
+  ssl_tsi_test_do_handshake_with_root_store();
   ssl_tsi_test_do_handshake_with_client_authentication();
+  ssl_tsi_test_do_handshake_with_client_authentication_and_root_store();
   ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain();
   ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain();
   ssl_tsi_test_do_handshake_with_bad_server_cert();