Skip to content

Commit d91a640

Browse files
committed
tls: Add support for session caching
1 parent f97bb10 commit d91a640

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[next]
2+
3+
* tls: Add support for session caching.
4+
15
[1.6.0] - 2021-10-03
26

37
* tls: Fix arguments of TLSWrappedSocket.sendto() method.

src/mbedtls/tls.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ cdef extern from "mbedtls/ssl.h" nogil:
350350
# mbedtls_ssl_set_hs_authmode
351351
const char* mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ctx)
352352
size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ctx)
353-
# mbedtls_ssl_get_verify_result
353+
int mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl)
354354
const char* mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl)
355355
const char* mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl)
356356
# mbedtls_ssl_get_record_expansion
@@ -441,7 +441,7 @@ cdef class DTLSConfiguration(_BaseConfiguration):
441441
cdef _set_cookie(self, _DTLSCookie cookie)
442442

443443

444-
cdef class _TLSSession:
444+
cdef class TLSSession:
445445
cdef mbedtls_ssl_session _ctx
446446

447447

src/mbedtls/tls.pyx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1151,7 +1151,7 @@ cdef class DTLSConfiguration(_BaseConfiguration):
11511151
DEFAULT_CIPHER_LIST = None
11521152

11531153

1154-
cdef class _TLSSession:
1154+
cdef class TLSSession:
11551155
def __cinit__(self):
11561156
"""Initialize SSL session structure."""
11571157
_tls.mbedtls_ssl_session_init(&self._ctx)
@@ -1163,6 +1163,24 @@ cdef class _TLSSession:
11631163
def __getstate__(self):
11641164
raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
11651165

1166+
def __repr__(self):
1167+
return "%s()" % type(self).__name__
1168+
1169+
def save(self, ClientContext context):
1170+
try:
1171+
_exc.check_error(
1172+
_tls.mbedtls_ssl_get_session(&context._ctx, &self._ctx)
1173+
)
1174+
except _exc.TLSError as exc:
1175+
raise ValueError(context) from exc
1176+
1177+
def resume(self, _BaseConfiguration configuration not None):
1178+
cdef ClientContext client = ClientContext(configuration)
1179+
_exc.check_error(
1180+
_tls.mbedtls_ssl_set_session(&client._ctx, &self._ctx)
1181+
)
1182+
return client
1183+
11661184

11671185
cdef class _BaseContext:
11681186
# _pep543._BaseContext
@@ -1204,6 +1222,10 @@ cdef class _BaseContext:
12041222
def _purpose(self):
12051223
return Purpose(self._conf._ctx.endpoint)
12061224

1225+
@property
1226+
def _verified(self):
1227+
return _tls.mbedtls_ssl_get_verify_result(&self._ctx) == 0
1228+
12071229
def _reset(self):
12081230
_exc.check_error(_tls.mbedtls_ssl_session_reset(&self._ctx))
12091231

tests/test_tls.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from mbedtls.tls import _enable_debug_output
2020
from mbedtls.tls import _PSKSToreProxy as PSKStoreProxy
2121
from mbedtls.tls import _set_debug_level
22-
from mbedtls.tls import _TLSSession as TLSSession
22+
from mbedtls.tls import TLSSession
2323
from mbedtls.x509 import CRT, CSR, BasicConstraints
2424

2525
try:
@@ -55,6 +55,12 @@ def __exit__(self, *exc_info):
5555
def __del__(self):
5656
self.stop()
5757

58+
@property
59+
def context(self):
60+
if self._sock is None:
61+
return None
62+
return self._sock.context
63+
5864
def do_handshake(self):
5965
if not self._sock:
6066
return
@@ -110,6 +116,12 @@ def __exit__(self, *exc_info):
110116
def __del__(self):
111117
self.stop()
112118

119+
@property
120+
def context(self):
121+
if self._sock is None:
122+
return None
123+
return self._sock.context
124+
113125
def start(self):
114126
if self._sock:
115127
self.stop()
@@ -356,6 +368,15 @@ def test_serialization(self, header):
356368
assert TLSRecordHeader.from_bytes(serialized) == header
357369

358370

371+
class TestTLSSession:
372+
@pytest.fixture
373+
def session(self):
374+
return TLSSession()
375+
376+
def test_repr(self, session):
377+
assert isinstance(repr(session), str)
378+
379+
359380
class Chain:
360381
@pytest.fixture(scope="class")
361382
def now(self):
@@ -862,3 +883,22 @@ def test_client_server(self, client, buffer, chunksize):
862883
break
863884

864885
assert client.echo(buffer, chunksize) == buffer
886+
887+
@pytest.mark.timeout(10)
888+
@pytest.mark.usefixtures("server")
889+
@pytest.mark.parametrize("ciphers", (ciphers_available(),), indirect=True)
890+
def test_session_caching(self, client, cli_conf):
891+
while True:
892+
try:
893+
client.do_handshake()
894+
except (WantReadError, WantWriteError):
895+
pass
896+
else:
897+
break
898+
899+
session = TLSSession()
900+
session.save(client.context)
901+
902+
new_context = session.resume(cli_conf)
903+
assert isinstance(new_context, ClientContext)
904+
assert new_context._verified

0 commit comments

Comments
 (0)