std::tls
std::tls provides TLS client/server
primitives for the hosted POSIX baseline using the built-in mbedTLS provider.
The initial goals are:
- a small but usable
std::tlssession API for clients and servers, - a transport-agnostic I/O model so TLS can be layered over
std::net::TCPStreamor custom runtimes , - end-to-end runnable tests that do not depend on real sockets (to keep the test suite runnable in sandboxed environments).
Provider, Linkage, and Toolchain Integration#
In default auto mode, Apple builds fall back to the built-in mbedTLS provider
for std::tls because the Network/Security-backed TLS implementation is not
wired yet. Explicit platform builds are strict and reject std::tls for now
with a diagnostic that names the missing provider mapping. Explicit builtin
builds use mbedTLS directly.
When the built-in provider path is active, silk build auto-links the built-in
mbedTLS static archives (libmbedtls.a, libmbedx509.a,
libmbedcrypto.a) from:
- the repo checkout:
vendor/lib/<target-layout>/, or - an installed prefix:
<prefix>/lib/silk/vendor/lib/<target-layout>/.
The current target layouts are x64-linux for glibc Linux x86_64,
x64-linux-musl for musl Linux x86_64, and aarch64-macos for Apple Silicon
macOS.
This avoids a runtime DT_NEEDED dependency on system mbedTLS shared libraries.
When the built-in archives are missing, silk build reports an error that
instructs the user to run zig build deps for the selected target.
The built-in mbedTLS in the Silk compiler repository is pinned (currently Mbed TLS 4.0.0). In mbedTLS 4.x, TLS depends on the PSA crypto subsystem for randomness and cryptographic operations.
Session constructors call psa_crypto_init() and then rely on
mbedtls_ssl_config_defaults(...) + mbedtls_ssl_setup(...) without explicitly
configuring a legacy f_rng callback (the historical mbedtls_ssl_conf_rng(...)
API is not present in mbedTLS 4.x).
Exported API#
Error model#
The current std::tls API uses std::result::Result(T, E) and a stable
TLSFailed error value instead of exposing raw mbedTLS error codes.
TLS I/O is transport-driven: when using a non-blocking transport (such as
MemPipe), operations may report that they would block and must be retried.
This is surfaced as a TLSFailed whose kind() is:
TLSErrorKind::WouldBlockReadTLSErrorKind::WouldBlockWrite
On TLS 1.3 connections, servers may send post-handshake NewSessionTicket
messages. mbedTLS reports these via MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET.
std::tls treats this as a retryable read condition (surfaced as
TLSErrorKind::WouldBlockRead) so higher-level callers can continue reading
application bytes.
Public error/value types in the Supported forms:
module std::tls;
import std::result;
enum TLSErrorKind {
OutOfMemory,
InvalidInput,
BadCertificate,
BadPrivateKey,
ConfigFailed,
SetupFailed,
WouldBlockRead,
WouldBlockWrite,
TLSFailure,
Unknown,
}
export error TLSFailed {
code: int,
}
export type TLSIntResult = std::result::Result(int, TLSFailed);
export type SessionResult = std::result::Result(Session, TLSFailed);
Session#
Session is a TLS state machine configured as either a client or a server.
Key operations:
Session.client() -> SessionResult— create a client session with a default configuration suitable for tests.Session.client_verified_system() -> SessionResult— create a client session configured to verify peer certificates using a system CA bundle.Session.client_verified_ca_pem(ca_pem: string) -> SessionResult— create a client session configured to verify peer certificates using a caller-provided PEM bundle.Session.server(cert_pem: string, key_pem: string) -> SessionResult— create a server session using PEM-encoded certificate and private key.set_bio_mempipe(bio: u64) -> void— attach aMemPipeendpoint context via mbedTLSssl_set_biousingstd::tls::mem_sendandstd::tls::mem_recv.set_bio_fd(fd: int) -> void— attach a hosted POSIX file descriptor as the underlying stream transport (for example astd::net::TCPStreamsocket).set_hostname(hostname: string) -> TLSFailed?— set the TLS hostname (SNI) and enable hostname verification for verified client sessions.handshake_step() -> TLSIntResult— advance the handshake state machine by one call (returnsOk(0)when complete;Err(...)on error).read(buf: std::arrays::ByteSlice) -> TLSIntResult— read decrypted application bytes.write(buf: std::arrays::ByteSlice) -> TLSIntResult— write application bytes.write_all(buf: std::arrays::ByteSlice) -> TLSFailed?— write all application bytes (retries internally onWouldBlockRead/WouldBlockWrite).write_string(s: string) -> TLSFailed?— convenience helper overwrite_all.close_notify() -> TLSFailed?— send a TLS close-notify alert.
Session implements std::interfaces::Drop and releases all associated mbedTLS
state on drop.
MemPipe#
MemPipe is an in-memory transport used for tests and for embedding scenarios
where the TLS peer-to-peer byte stream is modeled explicitly.
It provides two endpoint context pointers:
client_ctx() -> u64server_ctx() -> u64
These pointers can be passed to Session.set_bio_mempipe(...).
Considerations#
- The current
std::tlsAPI is intentionally small; higher-level features (hostname verification, CA stores, ALPN, session resumption, etc.) will be specified and implemented as the language and stdlib grow. - The Supported forms wires
Sessionto transports viaMemPipeand hosted POSIX file descriptors (set_bio_fd). General user-provided transport callbacks are planned but require additional FFI expressiveness beyond the current implementation. - The initial tests use
MemPipeinstead of real sockets somake testcan run in environments wheresocket(2)is restricted.
Source repository · Edit this page · View Markdown