diff --git a/.evergreen/generated_configs/variants.yml b/.evergreen/generated_configs/variants.yml
index 08c0dbbf36..8ba16273de 100644
--- a/.evergreen/generated_configs/variants.yml
+++ b/.evergreen/generated_configs/variants.yml
@@ -620,17 +620,19 @@ buildvariants:
       - macos-14
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: /Library/Frameworks/Python.Framework/Versions/3.9/bin/python3
   - name: pyopenssl-rhel8-python3.10
     tasks:
-      - name: .replica_set .auth .ssl .sync
-      - name: .7.0 .auth .ssl .sync
+      - name: .replica_set .auth .ssl .sync_async
+      - name: .7.0 .auth .ssl .sync_async
     display_name: PyOpenSSL RHEL8 Python3.10
     run_on:
       - rhel87-small
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: /opt/python/3.10/bin/python3
   - name: pyopenssl-rhel8-python3.11
@@ -642,6 +644,7 @@ buildvariants:
       - rhel87-small
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: /opt/python/3.11/bin/python3
   - name: pyopenssl-rhel8-python3.12
@@ -653,17 +656,19 @@ buildvariants:
       - rhel87-small
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: /opt/python/3.12/bin/python3
   - name: pyopenssl-win64-python3.13
     tasks:
-      - name: .replica_set .auth .ssl .sync
-      - name: .7.0 .auth .ssl .sync
+      - name: .replica_set .auth .ssl .sync_async
+      - name: .7.0 .auth .ssl .sync_async
     display_name: PyOpenSSL Win64 Python3.13
     run_on:
       - windows-64-vsMulti-small
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: C:/python/Python313/python.exe
   - name: pyopenssl-rhel8-pypy3.10
@@ -675,6 +680,7 @@ buildvariants:
       - rhel87-small
     batchtime: 10080
     expansions:
+      TEST_NAME: default
       SUB_TEST_NAME: pyopenssl
       PYTHON_BINARY: /opt/python/pypy3.10/bin/python3
 
diff --git a/.evergreen/scripts/generate_config.py b/.evergreen/scripts/generate_config.py
index 7b88be85b7..be1a960db2 100644
--- a/.evergreen/scripts/generate_config.py
+++ b/.evergreen/scripts/generate_config.py
@@ -250,7 +250,7 @@ def create_enterprise_auth_variants():
 def create_pyopenssl_variants():
     base_name = "PyOpenSSL"
     batchtime = BATCHTIME_WEEK
-    expansions = dict(SUB_TEST_NAME="pyopenssl")
+    expansions = dict(TEST_NAME="default", SUB_TEST_NAME="pyopenssl")
     variants = []
 
     for python in ALL_PYTHONS:
@@ -265,14 +265,25 @@ def create_pyopenssl_variants():
             host = DEFAULT_HOST
 
         display_name = get_variant_name(base_name, host, python=python)
-        variant = create_variant(
-            [f".replica_set .{auth} .{ssl} .sync", f".7.0 .{auth} .{ssl} .sync"],
-            display_name,
-            python=python,
-            host=host,
-            expansions=expansions,
-            batchtime=batchtime,
-        )
+        # only need to run some on async
+        if python in (CPYTHONS[1], CPYTHONS[-1]):
+            variant = create_variant(
+                [f".replica_set .{auth} .{ssl} .sync_async", f".7.0 .{auth} .{ssl} .sync_async"],
+                display_name,
+                python=python,
+                host=host,
+                expansions=expansions,
+                batchtime=batchtime,
+            )
+        else:
+            variant = create_variant(
+                [f".replica_set .{auth} .{ssl} .sync", f".7.0 .{auth} .{ssl} .sync"],
+                display_name,
+                python=python,
+                host=host,
+                expansions=expansions,
+                batchtime=batchtime,
+            )
         variants.append(variant)
 
     return variants
diff --git a/doc/changelog.rst b/doc/changelog.rst
index 46e7364f53..db344d4872 100644
--- a/doc/changelog.rst
+++ b/doc/changelog.rst
@@ -18,6 +18,8 @@ Version 4.12.1 is a bug fix release.
   Eventlet is actively being sunset by its maintainers and has compatibility issues with PyMongo's dnspython dependency.
 - Fixed a bug where MongoDB cluster topology changes could cause asynchronous operations to take much longer to complete
   due to holding the Topology lock while closing stale connections.
+- Fixed a bug that would cause AsyncMongoClient to attempt to use PyOpenSSL when available, resulting in errors such as
+  "pymongo.errors.ServerSelectionTimeoutError: 'SSLContext' object has no attribute 'wrap_bio'".
 
 Issues Resolved
 ...............
diff --git a/pymongo/asynchronous/encryption.py b/pymongo/asynchronous/encryption.py
index 71a694a619..9b0757b1a5 100644
--- a/pymongo/asynchronous/encryption.py
+++ b/pymongo/asynchronous/encryption.py
@@ -87,7 +87,7 @@
 from pymongo.results import BulkWriteResult, DeleteResult
 from pymongo.ssl_support import BLOCKING_IO_ERRORS, get_ssl_context
 from pymongo.typings import _DocumentType, _DocumentTypeArg
-from pymongo.uri_parser_shared import parse_host
+from pymongo.uri_parser_shared import _parse_kms_tls_options, parse_host
 from pymongo.write_concern import WriteConcern
 
 if TYPE_CHECKING:
@@ -157,6 +157,7 @@ def __init__(
         self.mongocryptd_client = mongocryptd_client
         self.opts = opts
         self._spawned = False
+        self._kms_ssl_contexts = opts._kms_ssl_contexts(_IS_SYNC)
 
     async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
         """Complete a KMS request.
@@ -168,7 +169,7 @@ async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
         endpoint = kms_context.endpoint
         message = kms_context.message
         provider = kms_context.kms_provider
-        ctx = self.opts._kms_ssl_contexts.get(provider)
+        ctx = self._kms_ssl_contexts.get(provider)
         if ctx is None:
             # Enable strict certificate verification, OCSP, match hostname, and
             # SNI using the system default CA certificates.
@@ -180,6 +181,7 @@ async def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
                 False,  # allow_invalid_certificates
                 False,  # allow_invalid_hostnames
                 False,  # disable_ocsp_endpoint_check
+                _IS_SYNC,
             )
         # CSOT: set timeout for socket creation.
         connect_timeout = max(_csot.clamp_remaining(_KMS_CONNECT_TIMEOUT), 0.001)
@@ -396,6 +398,8 @@ def __init__(self, client: AsyncMongoClient[_DocumentTypeArg], opts: AutoEncrypt
             encrypted_fields_map = _dict_to_bson(opts._encrypted_fields_map, False, _DATA_KEY_OPTS)
         self._bypass_auto_encryption = opts._bypass_auto_encryption
         self._internal_client = None
+        # parsing kms_ssl_contexts here so that parsing errors will be raised before internal clients are created
+        opts._kms_ssl_contexts(_IS_SYNC)
 
         def _get_internal_client(
             encrypter: _Encrypter, mongo_client: AsyncMongoClient[_DocumentTypeArg]
@@ -675,6 +679,7 @@ def __init__(
             kms_tls_options=kms_tls_options,
             key_expiration_ms=key_expiration_ms,
         )
+        self._kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
         self._io_callbacks: Optional[_EncryptionIO] = _EncryptionIO(
             None, key_vault_coll, None, opts
         )
diff --git a/pymongo/asynchronous/pool.py b/pymongo/asynchronous/pool.py
index 8b18ab927b..f4d5b174fa 100644
--- a/pymongo/asynchronous/pool.py
+++ b/pymongo/asynchronous/pool.py
@@ -76,6 +76,7 @@
 from pymongo.network_layer import AsyncNetworkingInterface, async_receive_message, async_sendall
 from pymongo.pool_options import PoolOptions
 from pymongo.pool_shared import (
+    SSLErrors,
     _CancellationContext,
     _configured_protocol_interface,
     _get_timeout_details,
@@ -86,7 +87,6 @@
 from pymongo.server_api import _add_to_command
 from pymongo.server_type import SERVER_TYPE
 from pymongo.socket_checker import SocketChecker
-from pymongo.ssl_support import SSLError
 
 if TYPE_CHECKING:
     from bson import CodecOptions
@@ -638,7 +638,7 @@ async def _raise_connection_failure(self, error: BaseException) -> NoReturn:
             reason = ConnectionClosedReason.ERROR
         await self.close_conn(reason)
         # SSLError from PyOpenSSL inherits directly from Exception.
-        if isinstance(error, (IOError, OSError, SSLError)):
+        if isinstance(error, (IOError, OSError, *SSLErrors)):
             details = _get_timeout_details(self.opts)
             _raise_connection_failure(self.address, error, timeout_details=details)
         else:
@@ -1052,7 +1052,7 @@ async def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> A
                     reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR),
                     error=ConnectionClosedReason.ERROR,
                 )
-            if isinstance(error, (IOError, OSError, SSLError)):
+            if isinstance(error, (IOError, OSError, *SSLErrors)):
                 details = _get_timeout_details(self.opts)
                 _raise_connection_failure(self.address, error, timeout_details=details)
 
diff --git a/pymongo/client_options.py b/pymongo/client_options.py
index a66e87c9f6..bd27dd4eb0 100644
--- a/pymongo/client_options.py
+++ b/pymongo/client_options.py
@@ -84,7 +84,9 @@ def _parse_read_concern(options: Mapping[str, Any]) -> ReadConcern:
     return ReadConcern(concern)
 
 
-def _parse_ssl_options(options: Mapping[str, Any]) -> tuple[Optional[SSLContext], bool]:
+def _parse_ssl_options(
+    options: Mapping[str, Any], is_sync: bool
+) -> tuple[Optional[SSLContext], bool]:
     """Parse ssl options."""
     use_tls = options.get("tls")
     if use_tls is not None:
@@ -138,6 +140,7 @@ def _parse_ssl_options(options: Mapping[str, Any]) -> tuple[Optional[SSLContext]
             allow_invalid_certificates,
             allow_invalid_hostnames,
             disable_ocsp_endpoint_check,
+            is_sync,
         )
         return ctx, allow_invalid_hostnames
     return None, allow_invalid_hostnames
@@ -167,7 +170,7 @@ def _parse_pool_options(
     compression_settings = CompressionSettings(
         options.get("compressors", []), options.get("zlibcompressionlevel", -1)
     )
-    ssl_context, tls_allow_invalid_hostnames = _parse_ssl_options(options)
+    ssl_context, tls_allow_invalid_hostnames = _parse_ssl_options(options, is_sync)
     load_balanced = options.get("loadbalanced")
     max_connecting = options.get("maxconnecting", common.MAX_CONNECTING)
     return PoolOptions(
diff --git a/pymongo/encryption_options.py b/pymongo/encryption_options.py
index 4cb94cba30..e9ad1c1e01 100644
--- a/pymongo/encryption_options.py
+++ b/pymongo/encryption_options.py
@@ -20,6 +20,8 @@
 
 from typing import TYPE_CHECKING, Any, Mapping, Optional
 
+from pymongo.uri_parser_shared import _parse_kms_tls_options
+
 try:
     import pymongocrypt  # type:ignore[import-untyped] # noqa: F401
 
@@ -32,9 +34,9 @@
 from bson import int64
 from pymongo.common import validate_is_mapping
 from pymongo.errors import ConfigurationError
-from pymongo.uri_parser_shared import _parse_kms_tls_options
 
 if TYPE_CHECKING:
+    from pymongo.pyopenssl_context import SSLContext
     from pymongo.typings import _AgnosticMongoClient, _DocumentTypeArg
 
 
@@ -236,10 +238,22 @@ def __init__(
         if not any("idleShutdownTimeoutSecs" in s for s in self._mongocryptd_spawn_args):
             self._mongocryptd_spawn_args.append("--idleShutdownTimeoutSecs=60")
         # Maps KMS provider name to a SSLContext.
-        self._kms_ssl_contexts = _parse_kms_tls_options(kms_tls_options)
+        self._kms_tls_options = kms_tls_options
+        self._sync_kms_ssl_contexts: Optional[dict[str, SSLContext]] = None
+        self._async_kms_ssl_contexts: Optional[dict[str, SSLContext]] = None
         self._bypass_query_analysis = bypass_query_analysis
         self._key_expiration_ms = key_expiration_ms
 
+    def _kms_ssl_contexts(self, is_sync: bool) -> dict[str, SSLContext]:
+        if is_sync:
+            if self._sync_kms_ssl_contexts is None:
+                self._sync_kms_ssl_contexts = _parse_kms_tls_options(self._kms_tls_options, True)
+            return self._sync_kms_ssl_contexts
+        else:
+            if self._async_kms_ssl_contexts is None:
+                self._async_kms_ssl_contexts = _parse_kms_tls_options(self._kms_tls_options, False)
+            return self._async_kms_ssl_contexts
+
 
 class RangeOpts:
     """Options to configure encrypted queries using the range algorithm."""
diff --git a/pymongo/network_layer.py b/pymongo/network_layer.py
index e287655c61..3fa180bf7a 100644
--- a/pymongo/network_layer.py
+++ b/pymongo/network_layer.py
@@ -46,22 +46,18 @@
     _HAVE_SSL = False
 
 try:
-    from pymongo.pyopenssl_context import (
-        BLOCKING_IO_LOOKUP_ERROR,
-        BLOCKING_IO_READ_ERROR,
-        BLOCKING_IO_WRITE_ERROR,
-        _sslConn,
-    )
+    from pymongo.pyopenssl_context import _sslConn
 
     _HAVE_PYOPENSSL = True
 except ImportError:
     _HAVE_PYOPENSSL = False
-    _sslConn = SSLSocket  # type: ignore
-    from pymongo.ssl_support import (  # type: ignore[assignment]
-        BLOCKING_IO_LOOKUP_ERROR,
-        BLOCKING_IO_READ_ERROR,
-        BLOCKING_IO_WRITE_ERROR,
-    )
+    _sslConn = SSLSocket  # type: ignore[assignment, misc]
+
+from pymongo.ssl_support import (
+    BLOCKING_IO_LOOKUP_ERROR,
+    BLOCKING_IO_READ_ERROR,
+    BLOCKING_IO_WRITE_ERROR,
+)
 
 if TYPE_CHECKING:
     from pymongo.asynchronous.pool import AsyncConnection
@@ -71,7 +67,7 @@
 _UNPACK_COMPRESSION_HEADER = struct.Struct("<iiB").unpack
 _POLL_TIMEOUT = 0.5
 # Errors raised by sockets (and TLS sockets) when in non-blocking mode.
-BLOCKING_IO_ERRORS = (BlockingIOError, BLOCKING_IO_LOOKUP_ERROR, *ssl_support.BLOCKING_IO_ERRORS)
+BLOCKING_IO_ERRORS = (BlockingIOError, *BLOCKING_IO_LOOKUP_ERROR, *ssl_support.BLOCKING_IO_ERRORS)
 
 
 # These socket-based I/O methods are for KMS requests and any other network operations that do not use
diff --git a/pymongo/pool_shared.py b/pymongo/pool_shared.py
index be7c416dc5..308ecef349 100644
--- a/pymongo/pool_shared.py
+++ b/pymongo/pool_shared.py
@@ -38,8 +38,9 @@
 )
 from pymongo.network_layer import AsyncNetworkingInterface, NetworkingInterface, PyMongoProtocol
 from pymongo.pool_options import PoolOptions
-from pymongo.ssl_support import HAS_SNI, SSLError
+from pymongo.ssl_support import PYSSLError, SSLError, _has_sni
 
+SSLErrors = (PYSSLError, SSLError)
 if TYPE_CHECKING:
     from pymongo.pyopenssl_context import _sslConn
     from pymongo.typings import _Address
@@ -138,7 +139,7 @@ def _raise_connection_failure(
         msg += format_timeout_details(timeout_details)
     if isinstance(error, socket.timeout):
         raise NetworkTimeout(msg) from error
-    elif isinstance(error, SSLError) and "timed out" in str(error):
+    elif isinstance(error, SSLErrors) and "timed out" in str(error):
         # Eventlet does not distinguish TLS network timeouts from other
         # SSLErrors (https://github.com/eventlet/eventlet/issues/692).
         # Luckily, we can work around this limitation because the phrase
@@ -279,7 +280,7 @@ async def _async_configured_socket(
     try:
         # We have to pass hostname / ip address to wrap_socket
         # to use SSLContext.check_hostname.
-        if HAS_SNI:
+        if _has_sni(False):
             loop = asyncio.get_running_loop()
             ssl_sock = await loop.run_in_executor(
                 None,
@@ -293,7 +294,7 @@ async def _async_configured_socket(
         # Raise _CertificateError directly like we do after match_hostname
         # below.
         raise
-    except (OSError, SSLError) as exc:
+    except (OSError, *SSLErrors) as exc:
         sock.close()
         # We raise AutoReconnect for transient and permanent SSL handshake
         # failures alike. Permanent handshake failures, like protocol
@@ -349,7 +350,7 @@ async def _configured_protocol_interface(
         # Raise _CertificateError directly like we do after match_hostname
         # below.
         raise
-    except (OSError, SSLError) as exc:
+    except (OSError, *SSLErrors) as exc:
         # We raise AutoReconnect for transient and permanent SSL handshake
         # failures alike. Permanent handshake failures, like protocol
         # mismatch, will be turned into ServerSelectionTimeoutErrors later.
@@ -458,7 +459,7 @@ def _configured_socket(address: _Address, options: PoolOptions) -> Union[socket.
     try:
         # We have to pass hostname / ip address to wrap_socket
         # to use SSLContext.check_hostname.
-        if HAS_SNI:
+        if _has_sni(True):
             ssl_sock = ssl_context.wrap_socket(sock, server_hostname=host)  # type: ignore[assignment, misc, unused-ignore]
         else:
             ssl_sock = ssl_context.wrap_socket(sock)  # type: ignore[assignment, misc, unused-ignore]
@@ -467,7 +468,7 @@ def _configured_socket(address: _Address, options: PoolOptions) -> Union[socket.
         # Raise _CertificateError directly like we do after match_hostname
         # below.
         raise
-    except (OSError, SSLError) as exc:
+    except (OSError, *SSLErrors) as exc:
         sock.close()
         # We raise AutoReconnect for transient and permanent SSL handshake
         # failures alike. Permanent handshake failures, like protocol
@@ -507,7 +508,7 @@ def _configured_socket_interface(address: _Address, options: PoolOptions) -> Net
     try:
         # We have to pass hostname / ip address to wrap_socket
         # to use SSLContext.check_hostname.
-        if HAS_SNI:
+        if _has_sni(True):
             ssl_sock = ssl_context.wrap_socket(sock, server_hostname=host)
         else:
             ssl_sock = ssl_context.wrap_socket(sock)
@@ -516,7 +517,7 @@ def _configured_socket_interface(address: _Address, options: PoolOptions) -> Net
         # Raise _CertificateError directly like we do after match_hostname
         # below.
         raise
-    except (OSError, SSLError) as exc:
+    except (OSError, *SSLErrors) as exc:
         sock.close()
         # We raise AutoReconnect for transient and permanent SSL handshake
         # failures alike. Permanent handshake failures, like protocol
diff --git a/pymongo/ssl_support.py b/pymongo/ssl_support.py
index 2e6a509e3e..beafc717eb 100644
--- a/pymongo/ssl_support.py
+++ b/pymongo/ssl_support.py
@@ -15,16 +15,19 @@
 """Support for SSL in PyMongo."""
 from __future__ import annotations
 
+import types
 import warnings
-from typing import Optional
+from typing import Any, Optional, Union
 
 from pymongo.errors import ConfigurationError
 
 HAVE_SSL = True
+HAVE_PYSSL = True
 
 try:
-    import pymongo.pyopenssl_context as _ssl
+    import pymongo.pyopenssl_context as _pyssl
 except (ImportError, AttributeError) as exc:
+    HAVE_PYSSL = False
     if isinstance(exc, AttributeError):
         warnings.warn(
             "Failed to use the installed version of PyOpenSSL. "
@@ -35,10 +38,10 @@
             UserWarning,
             stacklevel=2,
         )
-    try:
-        import pymongo.ssl_context as _ssl  # type: ignore[no-redef]
-    except ImportError:
-        HAVE_SSL = False
+try:
+    import pymongo.ssl_context as _ssl
+except ImportError:
+    HAVE_SSL = False
 
 
 if HAVE_SSL:
@@ -49,14 +52,29 @@
     import ssl as _stdlibssl  # noqa: F401
     from ssl import CERT_NONE, CERT_REQUIRED
 
-    HAS_SNI = _ssl.HAS_SNI
     IPADDR_SAFE = True
+
+    if HAVE_PYSSL:
+        PYSSLError: Any = _pyssl.SSLError
+        BLOCKING_IO_ERRORS: tuple = _ssl.BLOCKING_IO_ERRORS + _pyssl.BLOCKING_IO_ERRORS
+        BLOCKING_IO_READ_ERROR: tuple = (_pyssl.BLOCKING_IO_READ_ERROR, _ssl.BLOCKING_IO_READ_ERROR)
+        BLOCKING_IO_WRITE_ERROR: tuple = (
+            _pyssl.BLOCKING_IO_WRITE_ERROR,
+            _ssl.BLOCKING_IO_WRITE_ERROR,
+        )
+    else:
+        PYSSLError = _ssl.SSLError
+        BLOCKING_IO_ERRORS = _ssl.BLOCKING_IO_ERRORS
+        BLOCKING_IO_READ_ERROR = (_ssl.BLOCKING_IO_READ_ERROR,)
+        BLOCKING_IO_WRITE_ERROR = (_ssl.BLOCKING_IO_WRITE_ERROR,)
     SSLError = _ssl.SSLError
-    BLOCKING_IO_ERRORS = _ssl.BLOCKING_IO_ERRORS
-    BLOCKING_IO_READ_ERROR = _ssl.BLOCKING_IO_READ_ERROR
-    BLOCKING_IO_WRITE_ERROR = _ssl.BLOCKING_IO_WRITE_ERROR
     BLOCKING_IO_LOOKUP_ERROR = BLOCKING_IO_READ_ERROR
 
+    def _has_sni(is_sync: bool) -> bool:
+        if is_sync and HAVE_PYSSL:
+            return _pyssl.HAS_SNI
+        return _ssl.HAS_SNI
+
     def get_ssl_context(
         certfile: Optional[str],
         passphrase: Optional[str],
@@ -65,10 +83,15 @@ def get_ssl_context(
         allow_invalid_certificates: bool,
         allow_invalid_hostnames: bool,
         disable_ocsp_endpoint_check: bool,
-    ) -> _ssl.SSLContext:
+        is_sync: bool,
+    ) -> Union[_pyssl.SSLContext, _ssl.SSLContext]:  # type: ignore[name-defined]
         """Create and return an SSLContext object."""
+        if is_sync and HAVE_PYSSL:
+            ssl: types.ModuleType = _pyssl
+        else:
+            ssl = _ssl
         verify_mode = CERT_NONE if allow_invalid_certificates else CERT_REQUIRED
-        ctx = _ssl.SSLContext(_ssl.PROTOCOL_SSLv23)
+        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
         if verify_mode != CERT_NONE:
             ctx.check_hostname = not allow_invalid_hostnames
         else:
@@ -80,22 +103,20 @@ def get_ssl_context(
             # up to date versions of MongoDB 2.4 and above already disable
             # SSLv2 and SSLv3, python disables SSLv2 by default in >= 2.7.7
             # and >= 3.3.4 and SSLv3 in >= 3.4.3.
-            ctx.options |= _ssl.OP_NO_SSLv2
-            ctx.options |= _ssl.OP_NO_SSLv3
-            ctx.options |= _ssl.OP_NO_COMPRESSION
-            ctx.options |= _ssl.OP_NO_RENEGOTIATION
+            ctx.options |= ssl.OP_NO_SSLv2
+            ctx.options |= ssl.OP_NO_SSLv3
+            ctx.options |= ssl.OP_NO_COMPRESSION
+            ctx.options |= ssl.OP_NO_RENEGOTIATION
         if certfile is not None:
             try:
                 ctx.load_cert_chain(certfile, None, passphrase)
-            except _ssl.SSLError as exc:
+            except ssl.SSLError as exc:
                 raise ConfigurationError(f"Private key doesn't match certificate: {exc}") from None
         if crlfile is not None:
-            if _ssl.IS_PYOPENSSL:
+            if ssl.IS_PYOPENSSL:
                 raise ConfigurationError("tlsCRLFile cannot be used with PyOpenSSL")
             # Match the server's behavior.
-            ctx.verify_flags = getattr(  # type:ignore[attr-defined]
-                _ssl, "VERIFY_CRL_CHECK_LEAF", 0
-            )
+            ctx.verify_flags = getattr(ssl, "VERIFY_CRL_CHECK_LEAF", 0)
             ctx.load_verify_locations(crlfile)
         if ca_certs is not None:
             ctx.load_verify_locations(ca_certs)
@@ -109,9 +130,11 @@ def get_ssl_context(
     class SSLError(Exception):  # type: ignore
         pass
 
-    HAS_SNI = False
     IPADDR_SAFE = False
-    BLOCKING_IO_ERRORS = ()  # type:ignore[assignment]
+    BLOCKING_IO_ERRORS = ()
+
+    def _has_sni(is_sync: bool) -> bool:  # noqa: ARG001
+        return False
 
     def get_ssl_context(*dummy):  # type: ignore
         """No ssl module, raise ConfigurationError."""
diff --git a/pymongo/synchronous/encryption.py b/pymongo/synchronous/encryption.py
index ed631e135d..5f9bdac4b7 100644
--- a/pymongo/synchronous/encryption.py
+++ b/pymongo/synchronous/encryption.py
@@ -86,7 +86,7 @@
 from pymongo.synchronous.database import Database
 from pymongo.synchronous.mongo_client import MongoClient
 from pymongo.typings import _DocumentType, _DocumentTypeArg
-from pymongo.uri_parser_shared import parse_host
+from pymongo.uri_parser_shared import _parse_kms_tls_options, parse_host
 from pymongo.write_concern import WriteConcern
 
 if TYPE_CHECKING:
@@ -156,6 +156,7 @@ def __init__(
         self.mongocryptd_client = mongocryptd_client
         self.opts = opts
         self._spawned = False
+        self._kms_ssl_contexts = opts._kms_ssl_contexts(_IS_SYNC)
 
     def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
         """Complete a KMS request.
@@ -167,7 +168,7 @@ def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
         endpoint = kms_context.endpoint
         message = kms_context.message
         provider = kms_context.kms_provider
-        ctx = self.opts._kms_ssl_contexts.get(provider)
+        ctx = self._kms_ssl_contexts.get(provider)
         if ctx is None:
             # Enable strict certificate verification, OCSP, match hostname, and
             # SNI using the system default CA certificates.
@@ -179,6 +180,7 @@ def kms_request(self, kms_context: MongoCryptKmsContext) -> None:
                 False,  # allow_invalid_certificates
                 False,  # allow_invalid_hostnames
                 False,  # disable_ocsp_endpoint_check
+                _IS_SYNC,
             )
         # CSOT: set timeout for socket creation.
         connect_timeout = max(_csot.clamp_remaining(_KMS_CONNECT_TIMEOUT), 0.001)
@@ -393,6 +395,8 @@ def __init__(self, client: MongoClient[_DocumentTypeArg], opts: AutoEncryptionOp
             encrypted_fields_map = _dict_to_bson(opts._encrypted_fields_map, False, _DATA_KEY_OPTS)
         self._bypass_auto_encryption = opts._bypass_auto_encryption
         self._internal_client = None
+        # parsing kms_ssl_contexts here so that parsing errors will be raised before internal clients are created
+        opts._kms_ssl_contexts(_IS_SYNC)
 
         def _get_internal_client(
             encrypter: _Encrypter, mongo_client: MongoClient[_DocumentTypeArg]
@@ -668,6 +672,7 @@ def __init__(
             kms_tls_options=kms_tls_options,
             key_expiration_ms=key_expiration_ms,
         )
+        self._kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
         self._io_callbacks: Optional[_EncryptionIO] = _EncryptionIO(
             None, key_vault_coll, None, opts
         )
diff --git a/pymongo/synchronous/pool.py b/pymongo/synchronous/pool.py
index b3eec64f27..44aec31a86 100644
--- a/pymongo/synchronous/pool.py
+++ b/pymongo/synchronous/pool.py
@@ -73,6 +73,7 @@
 from pymongo.network_layer import NetworkingInterface, receive_message, sendall
 from pymongo.pool_options import PoolOptions
 from pymongo.pool_shared import (
+    SSLErrors,
     _CancellationContext,
     _configured_socket_interface,
     _get_timeout_details,
@@ -83,7 +84,6 @@
 from pymongo.server_api import _add_to_command
 from pymongo.server_type import SERVER_TYPE
 from pymongo.socket_checker import SocketChecker
-from pymongo.ssl_support import SSLError
 from pymongo.synchronous.client_session import _validate_session_write_concern
 from pymongo.synchronous.helpers import _handle_reauth
 from pymongo.synchronous.network import command
@@ -636,7 +636,7 @@ def _raise_connection_failure(self, error: BaseException) -> NoReturn:
             reason = ConnectionClosedReason.ERROR
         self.close_conn(reason)
         # SSLError from PyOpenSSL inherits directly from Exception.
-        if isinstance(error, (IOError, OSError, SSLError)):
+        if isinstance(error, (IOError, OSError, *SSLErrors)):
             details = _get_timeout_details(self.opts)
             _raise_connection_failure(self.address, error, timeout_details=details)
         else:
@@ -1048,7 +1048,7 @@ def connect(self, handler: Optional[_MongoClientErrorHandler] = None) -> Connect
                     reason=_verbose_connection_error_reason(ConnectionClosedReason.ERROR),
                     error=ConnectionClosedReason.ERROR,
                 )
-            if isinstance(error, (IOError, OSError, SSLError)):
+            if isinstance(error, (IOError, OSError, *SSLErrors)):
                 details = _get_timeout_details(self.opts)
                 _raise_connection_failure(self.address, error, timeout_details=details)
 
diff --git a/pymongo/uri_parser_shared.py b/pymongo/uri_parser_shared.py
index e7ba4c9fb5..0cef176bf1 100644
--- a/pymongo/uri_parser_shared.py
+++ b/pymongo/uri_parser_shared.py
@@ -420,7 +420,10 @@ def _check_options(nodes: Sized, options: Mapping[str, Any]) -> None:
             raise ConfigurationError("Cannot specify replicaSet with loadBalanced=true")
 
 
-def _parse_kms_tls_options(kms_tls_options: Optional[Mapping[str, Any]]) -> dict[str, SSLContext]:
+def _parse_kms_tls_options(
+    kms_tls_options: Optional[Mapping[str, Any]],
+    is_sync: bool,
+) -> dict[str, SSLContext]:
     """Parse KMS TLS connection options."""
     if not kms_tls_options:
         return {}
@@ -435,7 +438,7 @@ def _parse_kms_tls_options(kms_tls_options: Optional[Mapping[str, Any]]) -> dict
         opts = _handle_security_options(opts)
         opts = _normalize_options(opts)
         opts = cast(_CaseInsensitiveDictionary, validate_options(opts))
-        ssl_context, allow_invalid_hostnames = _parse_ssl_options(opts)
+        ssl_context, allow_invalid_hostnames = _parse_ssl_options(opts, is_sync)
         if ssl_context is None:
             raise ConfigurationError("TLS is required for KMS providers")
         if allow_invalid_hostnames:
diff --git a/test/asynchronous/test_encryption.py b/test/asynchronous/test_encryption.py
index f9b03f6303..9e8758a1cd 100644
--- a/test/asynchronous/test_encryption.py
+++ b/test/asynchronous/test_encryption.py
@@ -41,6 +41,7 @@
 from pymongo.asynchronous.collection import AsyncCollection
 from pymongo.asynchronous.helpers import anext
 from pymongo.daemon import _spawn_daemon
+from pymongo.uri_parser_shared import _parse_kms_tls_options
 
 try:
     from pymongo.pyopenssl_context import IS_PYOPENSSL
@@ -141,7 +142,7 @@ def test_init(self):
         self.assertEqual(opts._mongocryptd_bypass_spawn, False)
         self.assertEqual(opts._mongocryptd_spawn_path, "mongocryptd")
         self.assertEqual(opts._mongocryptd_spawn_args, ["--idleShutdownTimeoutSecs=60"])
-        self.assertEqual(opts._kms_ssl_contexts, {})
+        self.assertEqual(opts._kms_tls_options, None)
 
     @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
     def test_init_spawn_args(self):
@@ -165,30 +166,38 @@ def test_init_spawn_args(self):
         )
 
     @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
-    def test_init_kms_tls_options(self):
+    async def test_init_kms_tls_options(self):
         # Error cases:
+        opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
         with self.assertRaisesRegex(TypeError, r'kms_tls_options\["kmip"\] must be a dict'):
-            AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
+            AsyncMongoClient(auto_encryption_opts=opts)
+
         tls_opts: Any
         for tls_opts in [
             {"kmip": {"tls": True, "tlsInsecure": True}},
             {"kmip": {"tls": True, "tlsAllowInvalidCertificates": True}},
             {"kmip": {"tls": True, "tlsAllowInvalidHostnames": True}},
         ]:
+            opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
             with self.assertRaisesRegex(ConfigurationError, "Insecure TLS options prohibited"):
-                opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
+                AsyncMongoClient(auto_encryption_opts=opts)
+        opts = AutoEncryptionOpts(
+            {}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}}
+        )
         with self.assertRaises(FileNotFoundError):
-            AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}})
+            AsyncMongoClient(auto_encryption_opts=opts)
         # Success cases:
         tls_opts: Any
         for tls_opts in [None, {}]:
             opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
-            self.assertEqual(opts._kms_ssl_contexts, {})
+            kms_tls_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+            self.assertEqual(kms_tls_contexts, {})
         opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tls": True}, "aws": {}})
-        ctx = opts._kms_ssl_contexts["kmip"]
+        _kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+        ctx = _kms_ssl_contexts["kmip"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
-        ctx = opts._kms_ssl_contexts["aws"]
+        ctx = _kms_ssl_contexts["aws"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
         opts = AutoEncryptionOpts(
@@ -196,7 +205,8 @@ def test_init_kms_tls_options(self):
             "k.d",
             kms_tls_options={"kmip": {"tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM}},
         )
-        ctx = opts._kms_ssl_contexts["kmip"]
+        _kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+        ctx = _kms_ssl_contexts["kmip"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
 
@@ -2225,7 +2235,7 @@ async def test_05_tlsDisableOCSPEndpointCheck_is_permitted(self):
         encryption = self.create_client_encryption(
             providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=options
         )
-        ctx = encryption._io_callbacks.opts._kms_ssl_contexts["aws"]
+        ctx = encryption._io_callbacks._kms_ssl_contexts["aws"]
         if not hasattr(ctx, "check_ocsp_endpoint"):
             raise self.skipTest("OCSP not enabled")
         self.assertFalse(ctx.check_ocsp_endpoint)
diff --git a/test/asynchronous/test_ssl.py b/test/asynchronous/test_ssl.py
index 4d7566a61d..023ee91680 100644
--- a/test/asynchronous/test_ssl.py
+++ b/test/asynchronous/test_ssl.py
@@ -43,7 +43,7 @@
 from pymongo import AsyncMongoClient, ssl_support
 from pymongo.errors import ConfigurationError, ConnectionFailure, OperationFailure
 from pymongo.hello import HelloCompat
-from pymongo.ssl_support import HAVE_SSL, _ssl, get_ssl_context
+from pymongo.ssl_support import HAVE_PYSSL, HAVE_SSL, _ssl, get_ssl_context
 from pymongo.write_concern import WriteConcern
 
 _HAVE_PYOPENSSL = False
@@ -134,7 +134,7 @@ def test_config_ssl(self):
 
     @unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
     def test_use_pyopenssl_when_available(self):
-        self.assertTrue(_ssl.IS_PYOPENSSL)
+        self.assertTrue(HAVE_PYSSL)
 
     @unittest.skipUnless(_HAVE_PYOPENSSL, "Cannot test without PyOpenSSL")
     def test_load_trusted_ca_certs(self):
@@ -180,7 +180,7 @@ async def test_tlsCertificateKeyFilePassword(self):
         #
         #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
         #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
-        if not hasattr(ssl, "SSLContext") and not _ssl.IS_PYOPENSSL:
+        if not hasattr(ssl, "SSLContext") and not HAVE_PYSSL:
             self.assertRaises(
                 ConfigurationError,
                 self.simple_client,
@@ -312,13 +312,13 @@ async def test_cert_ssl_validation_hostname_matching(self):
         #
         #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
         #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
-        ctx = get_ssl_context(None, None, None, None, True, True, False)
+        ctx = get_ssl_context(None, None, None, None, True, True, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, True, False, False)
+        ctx = get_ssl_context(None, None, None, None, True, False, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, False, True, False)
+        ctx = get_ssl_context(None, None, None, None, False, True, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, False, False, False)
+        ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
         self.assertTrue(ctx.check_hostname)
 
         response = await self.client.admin.command(HelloCompat.LEGACY_CMD)
@@ -379,10 +379,11 @@ async def test_cert_ssl_validation_hostname_matching(self):
             )
 
     @async_client_context.require_tlsCertificateKeyFile
+    @async_client_context.require_sync
     @async_client_context.require_no_api_version
     @ignore_deprecations
     async def test_tlsCRLFile_support(self):
-        if not hasattr(ssl, "VERIFY_CRL_CHECK_LEAF") or _ssl.IS_PYOPENSSL:
+        if not hasattr(ssl, "VERIFY_CRL_CHECK_LEAF") or HAVE_PYSSL:
             self.assertRaises(
                 ConfigurationError,
                 self.simple_client,
@@ -473,7 +474,7 @@ async def test_validation_with_system_ca_certs(self):
         )
 
     def test_system_certs_config_error(self):
-        ctx = get_ssl_context(None, None, None, None, True, True, False)
+        ctx = get_ssl_context(None, None, None, None, True, True, False, _IS_SYNC)
         if (sys.platform != "win32" and hasattr(ctx, "set_default_verify_paths")) or hasattr(
             ctx, "load_default_certs"
         ):
@@ -504,11 +505,11 @@ def test_certifi_support(self):
         # Force the test on Windows, regardless of environment.
         ssl_support.HAVE_WINCERTSTORE = False
         try:
-            ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False)
+            ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False, _IS_SYNC)
             ssl_sock = ctx.wrap_socket(socket.socket())
             self.assertEqual(ssl_sock.ca_certs, CA_PEM)
 
-            ctx = get_ssl_context(None, None, None, None, False, False, False)
+            ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
             ssl_sock = ctx.wrap_socket(socket.socket())
             self.assertEqual(ssl_sock.ca_certs, ssl_support.certifi.where())
         finally:
@@ -525,11 +526,11 @@ def test_wincertstore(self):
         if not ssl_support.HAVE_WINCERTSTORE:
             raise SkipTest("Need wincertstore to test wincertstore.")
 
-        ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False)
+        ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False, _IS_SYNC)
         ssl_sock = ctx.wrap_socket(socket.socket())
         self.assertEqual(ssl_sock.ca_certs, CA_PEM)
 
-        ctx = get_ssl_context(None, None, None, None, False, False, False)
+        ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
         ssl_sock = ctx.wrap_socket(socket.socket())
         self.assertEqual(ssl_sock.ca_certs, ssl_support._WINCERTS.name)
 
@@ -663,6 +664,16 @@ def remove(path):
         ) as client:
             self.assertTrue(await client.admin.command("ping"))
 
+    @async_client_context.require_async
+    @unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
+    @unittest.skipUnless(HAVE_SSL, "The ssl module is not available.")
+    async def test_pyopenssl_ignored_in_async(self):
+        client = AsyncMongoClient(
+            "mongodb://localhost:27017?tls=true&tlsAllowInvalidCertificates=true"
+        )
+        await client.admin.command("ping")  # command doesn't matter, just needs it to connect
+        await client.close()
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/test/atlas/test_connection.py b/test/atlas/test_connection.py
index 3d34ff326e..a3e8b0b1d5 100644
--- a/test/atlas/test_connection.py
+++ b/test/atlas/test_connection.py
@@ -26,7 +26,7 @@
 sys.path[0:0] = [""]
 
 import pymongo
-from pymongo.ssl_support import HAS_SNI
+from pymongo.ssl_support import _has_sni
 
 pytestmark = pytest.mark.atlas_connect
 
@@ -57,7 +57,7 @@ def connect(self, uri):
         # No auth error
         client.test.test.count_documents({})
 
-    @unittest.skipUnless(HAS_SNI, "Free tier requires SNI support")
+    @unittest.skipUnless(_has_sni(True), "Free tier requires SNI support")
     def test_free_tier(self):
         self.connect(URIS["ATLAS_FREE"])
 
@@ -80,7 +80,7 @@ def connect_srv(self, uri):
         self.connect(uri)
         self.assertIn("mongodb+srv://", uri)
 
-    @unittest.skipUnless(HAS_SNI, "Free tier requires SNI support")
+    @unittest.skipUnless(_has_sni(True), "Free tier requires SNI support")
     def test_srv_free_tier(self):
         self.connect_srv(URIS["ATLAS_SRV_FREE"])
 
diff --git a/test/test_encryption.py b/test/test_encryption.py
index 5bbf8c8ad8..4b055b68d3 100644
--- a/test/test_encryption.py
+++ b/test/test_encryption.py
@@ -41,6 +41,7 @@
 from pymongo.daemon import _spawn_daemon
 from pymongo.synchronous.collection import Collection
 from pymongo.synchronous.helpers import next
+from pymongo.uri_parser_shared import _parse_kms_tls_options
 
 try:
     from pymongo.pyopenssl_context import IS_PYOPENSSL
@@ -141,7 +142,7 @@ def test_init(self):
         self.assertEqual(opts._mongocryptd_bypass_spawn, False)
         self.assertEqual(opts._mongocryptd_spawn_path, "mongocryptd")
         self.assertEqual(opts._mongocryptd_spawn_args, ["--idleShutdownTimeoutSecs=60"])
-        self.assertEqual(opts._kms_ssl_contexts, {})
+        self.assertEqual(opts._kms_tls_options, None)
 
     @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
     def test_init_spawn_args(self):
@@ -167,28 +168,36 @@ def test_init_spawn_args(self):
     @unittest.skipUnless(_HAVE_PYMONGOCRYPT, "pymongocrypt is not installed")
     def test_init_kms_tls_options(self):
         # Error cases:
+        opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
         with self.assertRaisesRegex(TypeError, r'kms_tls_options\["kmip"\] must be a dict'):
-            AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": 1})
+            MongoClient(auto_encryption_opts=opts)
+
         tls_opts: Any
         for tls_opts in [
             {"kmip": {"tls": True, "tlsInsecure": True}},
             {"kmip": {"tls": True, "tlsAllowInvalidCertificates": True}},
             {"kmip": {"tls": True, "tlsAllowInvalidHostnames": True}},
         ]:
+            opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
             with self.assertRaisesRegex(ConfigurationError, "Insecure TLS options prohibited"):
-                opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
+                MongoClient(auto_encryption_opts=opts)
+        opts = AutoEncryptionOpts(
+            {}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}}
+        )
         with self.assertRaises(FileNotFoundError):
-            AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tlsCAFile": "does-not-exist"}})
+            MongoClient(auto_encryption_opts=opts)
         # Success cases:
         tls_opts: Any
         for tls_opts in [None, {}]:
             opts = AutoEncryptionOpts({}, "k.d", kms_tls_options=tls_opts)
-            self.assertEqual(opts._kms_ssl_contexts, {})
+            kms_tls_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+            self.assertEqual(kms_tls_contexts, {})
         opts = AutoEncryptionOpts({}, "k.d", kms_tls_options={"kmip": {"tls": True}, "aws": {}})
-        ctx = opts._kms_ssl_contexts["kmip"]
+        _kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+        ctx = _kms_ssl_contexts["kmip"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
-        ctx = opts._kms_ssl_contexts["aws"]
+        ctx = _kms_ssl_contexts["aws"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
         opts = AutoEncryptionOpts(
@@ -196,7 +205,8 @@ def test_init_kms_tls_options(self):
             "k.d",
             kms_tls_options={"kmip": {"tlsCAFile": CA_PEM, "tlsCertificateKeyFile": CLIENT_PEM}},
         )
-        ctx = opts._kms_ssl_contexts["kmip"]
+        _kms_ssl_contexts = _parse_kms_tls_options(opts._kms_tls_options, _IS_SYNC)
+        ctx = _kms_ssl_contexts["kmip"]
         self.assertEqual(ctx.check_hostname, True)
         self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED)
 
@@ -2217,7 +2227,7 @@ def test_05_tlsDisableOCSPEndpointCheck_is_permitted(self):
         encryption = self.create_client_encryption(
             providers, "keyvault.datakeys", self.client, OPTS, kms_tls_options=options
         )
-        ctx = encryption._io_callbacks.opts._kms_ssl_contexts["aws"]
+        ctx = encryption._io_callbacks._kms_ssl_contexts["aws"]
         if not hasattr(ctx, "check_ocsp_endpoint"):
             raise self.skipTest("OCSP not enabled")
         self.assertFalse(ctx.check_ocsp_endpoint)
diff --git a/test/test_ssl.py b/test/test_ssl.py
index 7decc8203d..93a4b4e6ec 100644
--- a/test/test_ssl.py
+++ b/test/test_ssl.py
@@ -43,7 +43,7 @@
 from pymongo import MongoClient, ssl_support
 from pymongo.errors import ConfigurationError, ConnectionFailure, OperationFailure
 from pymongo.hello import HelloCompat
-from pymongo.ssl_support import HAVE_SSL, _ssl, get_ssl_context
+from pymongo.ssl_support import HAVE_PYSSL, HAVE_SSL, _ssl, get_ssl_context
 from pymongo.write_concern import WriteConcern
 
 _HAVE_PYOPENSSL = False
@@ -134,7 +134,7 @@ def test_config_ssl(self):
 
     @unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
     def test_use_pyopenssl_when_available(self):
-        self.assertTrue(_ssl.IS_PYOPENSSL)
+        self.assertTrue(HAVE_PYSSL)
 
     @unittest.skipUnless(_HAVE_PYOPENSSL, "Cannot test without PyOpenSSL")
     def test_load_trusted_ca_certs(self):
@@ -180,7 +180,7 @@ def test_tlsCertificateKeyFilePassword(self):
         #
         #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
         #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
-        if not hasattr(ssl, "SSLContext") and not _ssl.IS_PYOPENSSL:
+        if not hasattr(ssl, "SSLContext") and not HAVE_PYSSL:
             self.assertRaises(
                 ConfigurationError,
                 self.simple_client,
@@ -312,13 +312,13 @@ def test_cert_ssl_validation_hostname_matching(self):
         #
         #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
         #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
-        ctx = get_ssl_context(None, None, None, None, True, True, False)
+        ctx = get_ssl_context(None, None, None, None, True, True, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, True, False, False)
+        ctx = get_ssl_context(None, None, None, None, True, False, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, False, True, False)
+        ctx = get_ssl_context(None, None, None, None, False, True, False, _IS_SYNC)
         self.assertFalse(ctx.check_hostname)
-        ctx = get_ssl_context(None, None, None, None, False, False, False)
+        ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
         self.assertTrue(ctx.check_hostname)
 
         response = self.client.admin.command(HelloCompat.LEGACY_CMD)
@@ -379,10 +379,11 @@ def test_cert_ssl_validation_hostname_matching(self):
             )
 
     @client_context.require_tlsCertificateKeyFile
+    @client_context.require_sync
     @client_context.require_no_api_version
     @ignore_deprecations
     def test_tlsCRLFile_support(self):
-        if not hasattr(ssl, "VERIFY_CRL_CHECK_LEAF") or _ssl.IS_PYOPENSSL:
+        if not hasattr(ssl, "VERIFY_CRL_CHECK_LEAF") or HAVE_PYSSL:
             self.assertRaises(
                 ConfigurationError,
                 self.simple_client,
@@ -473,7 +474,7 @@ def test_validation_with_system_ca_certs(self):
         )
 
     def test_system_certs_config_error(self):
-        ctx = get_ssl_context(None, None, None, None, True, True, False)
+        ctx = get_ssl_context(None, None, None, None, True, True, False, _IS_SYNC)
         if (sys.platform != "win32" and hasattr(ctx, "set_default_verify_paths")) or hasattr(
             ctx, "load_default_certs"
         ):
@@ -504,11 +505,11 @@ def test_certifi_support(self):
         # Force the test on Windows, regardless of environment.
         ssl_support.HAVE_WINCERTSTORE = False
         try:
-            ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False)
+            ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False, _IS_SYNC)
             ssl_sock = ctx.wrap_socket(socket.socket())
             self.assertEqual(ssl_sock.ca_certs, CA_PEM)
 
-            ctx = get_ssl_context(None, None, None, None, False, False, False)
+            ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
             ssl_sock = ctx.wrap_socket(socket.socket())
             self.assertEqual(ssl_sock.ca_certs, ssl_support.certifi.where())
         finally:
@@ -525,11 +526,11 @@ def test_wincertstore(self):
         if not ssl_support.HAVE_WINCERTSTORE:
             raise SkipTest("Need wincertstore to test wincertstore.")
 
-        ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False)
+        ctx = get_ssl_context(None, None, CA_PEM, None, False, False, False, _IS_SYNC)
         ssl_sock = ctx.wrap_socket(socket.socket())
         self.assertEqual(ssl_sock.ca_certs, CA_PEM)
 
-        ctx = get_ssl_context(None, None, None, None, False, False, False)
+        ctx = get_ssl_context(None, None, None, None, False, False, False, _IS_SYNC)
         ssl_sock = ctx.wrap_socket(socket.socket())
         self.assertEqual(ssl_sock.ca_certs, ssl_support._WINCERTS.name)
 
@@ -663,6 +664,14 @@ def remove(path):
         ) as client:
             self.assertTrue(client.admin.command("ping"))
 
+    @client_context.require_async
+    @unittest.skipUnless(_HAVE_PYOPENSSL, "PyOpenSSL is not available.")
+    @unittest.skipUnless(HAVE_SSL, "The ssl module is not available.")
+    def test_pyopenssl_ignored_in_async(self):
+        client = MongoClient("mongodb://localhost:27017?tls=true&tlsAllowInvalidCertificates=true")
+        client.admin.command("ping")  # command doesn't matter, just needs it to connect
+        client.close()
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/ocsptest.py b/tools/ocsptest.py
index 521d048f79..8596db226d 100644
--- a/tools/ocsptest.py
+++ b/tools/ocsptest.py
@@ -35,6 +35,7 @@ def check_ocsp(host: str, port: int, capath: str) -> None:
         False,  # allow_invalid_certificates
         False,  # allow_invalid_hostnames
         False,
+        True,  # is sync
     )  # disable_ocsp_endpoint_check
 
     # Ensure we're using pyOpenSSL.