

# [`std::tls`](/silk/docs/std/tls/)

[`std::tls`](/silk/docs/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::tls`](/silk/docs/std/tls/) session API for clients and servers,
- a transport-agnostic I/O model so TLS can be layered over [`std::net::TCPStream`](/silk/docs/std/networking/)
 or 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`](/silk/docs/std/tls/) because the Network/Security-backed TLS implementation is not
wired yet. Explicit `platform` builds are strict and reject [`std::tls`](/silk/docs/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>/`](https://github.com/oro-computer/silk/tree/master/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`](/silk/docs/std/tls/) API uses [`std::result::Result(T, E)`](/silk/docs/std/result/) 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::WouldBlockRead`
- `TLSErrorKind::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`](/silk/docs/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:

```silk
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 a `MemPipe` endpoint context via
 mbedTLS `ssl_set_bio` using [`std::tls::mem_send`](/silk/docs/std/tls/) and [`std::tls::mem_recv`](/silk/docs/std/tls/).
- `set_bio_fd(fd: int) -> void` — attach a hosted POSIX file descriptor as the
 underlying stream transport (for example a [`std::net::TCPStream`](/silk/docs/std/networking/) socket).
- `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 (returns `Ok(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 on `WouldBlockRead` /
 `WouldBlockWrite`).
- `write_string(s: string) -> TLSFailed?` — convenience helper over
 `write_all`.
- `close_notify() -> TLSFailed?` — send a TLS close-notify alert.

`Session` implements [`std::interfaces::Drop`](/silk/docs/std/interfaces/) 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() -> u64`
- `server_ctx() -> u64`

These pointers can be passed to `Session.set_bio_mempipe(...)`.

## Considerations

- The current [`std::tls`](/silk/docs/std/tls/) API 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 `Session` to transports via `MemPipe` and 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 `MemPipe` instead of real sockets so `make test` can run
 in environments where `socket(2)` is restricted.
