async def _start_tls_connection(
        self,
        underlying_transport: asyncio.Transport,
        req: "ClientRequest",
        timeout: "ClientTimeout",
        client_error: Type[Exception] = ClientConnectorError,
    ) -> Tuple[asyncio.BaseTransport, ResponseHandler]:
        """Wrap the raw TCP transport with TLS."""
        tls_proto = self._factory()  # Create a brand new proto for TLS

        # Safety of the `cast()` call here is based on the fact that
        # internally `_get_ssl_context()` only returns `None` when
        # `req.is_ssl()` evaluates to `False` which is never gonna happen
        # in this code path. Of course, it's rather fragile
        # maintainability-wise but this is to be solved separately.
        sslcontext = cast(ssl.SSLContext, self._get_ssl_context(req))

        try:
            async with ceil_timeout(timeout.sock_connect):
                try:
                    tls_transport = await self._loop.start_tls(
                        underlying_transport,
                        tls_proto,
                        sslcontext,
                        server_hostname=req.host,
                        ssl_handshake_timeout=timeout.total,
                    )
                except BaseException:
                    # We need to close the underlying transport since
                    # `start_tls()` probably failed before it had a
                    # chance to do this:
                    underlying_transport.close()
                    raise
        except cert_errors as exc:
            raise ClientConnectorCertificateError(req.connection_key, exc) from exc
        except ssl_errors as exc:
            raise ClientConnectorSSLError(req.connection_key, exc) from exc
        except OSError as exc:
            if exc.errno is None and isinstance(exc, asyncio.TimeoutError):
                raise
            raise client_error(req.connection_key, exc) from exc
        except TypeError as type_err:
            # Example cause looks like this:
            # TypeError: transport <asyncio.sslproto._SSLProtocolTransport
            # object at 0x7f760615e460> is not supported by start_tls()

            raise ClientConnectionError(
                "Cannot initialize a TLS-in-TLS connection to host "
                f"{req.host!s}:{req.port:d} through an underlying connection "
                f"to an HTTPS proxy {req.proxy!s} ssl:{req.ssl or 'default'} "
                f"[{type_err!s}]"
            ) from type_err
        else:
            tls_proto.connection_made(
                tls_transport
            )  # Kick the state machine of the new TLS protocol

        return tls_transport, tls_proto
Wrap the raw TCP transport with TLS.
lib/aiohttp/connector.py