API reference
On this page 401
Every declaration below is extracted from zig-tls's source, with the doc comments as written there. A declaration listed without prose is public but undocumented in the source.
Root
max_ciphertext_record_len
const max_ciphertext_record_len = @import("cipher.zig").max_ciphertext_record_len
input_buffer_len
const input_buffer_len = max_ciphertext_record_len; // 16645 bytes
Buffer of this size will fit any tls ciphertext record sent by other side. To decrytp we need full record, smalled buffer will not work in general case. Bigger can be used for performance reason.
output_buffer_len
const output_buffer_len = @import("cipher.zig").max_encrypted_record_len; // 16469 bytes
Needed output buffer during handshake is the size of the tls hello message, which is (when client authentication is not used) ~1600 bytes. After handshake it limits how big tls record can be produced. This suggested value can hold max ciphertext record produced with this implementation.
Connection
const Connection = @import("connection.zig").Connection
ecdsa_p256
const ecdsa_p256 = @import("crypto/ecdsa_p256.zig")
P-256 ECDSA (CertificateVerify hot path, bench micro-benchmarks).
rsa
const rsa = @import("rsa/rsa.zig")
Low-level RSA primitives (PKCS#1 v1.5 / PSS sign+verify, public/private key parsing incl. SPKI). Exposed so consumers can do RSA outside the TLS handshake — e.g. DKIM signing/verification.
clientFromStream
inline fn clientFromStream(stream: anytype, opt: config.Client) !Connection
Upgrades existing stream to the tls connection by the client tls handshake.
client
fn client(input: *Io.Reader, output: *Io.Writer, opt: config.Client) !Connection
serverFromStream
inline fn serverFromStream(stream: anytype, opt: config.Server) !Connection
Upgrades existing stream to the tls connection by the server side tls handshake.
server
fn server(input: *Io.Reader, output: *Io.Writer, opt: config.Server) !Connection
Cipher
const Cipher = @import("cipher.zig").Cipher
Record
const Record = @import("record.zig").Record
record_header_len
const record_header_len = @import("record.zig").header_len
config
const config = struct
proto
const proto = @import("protocol.zig")
CipherSuite
const CipherSuite = @import("cipher.zig").CipherSuite
PrivateKey
const PrivateKey = @import("PrivateKey.zig")
NamedGroup
const NamedGroup = proto.NamedGroup
Version
const Version = proto.Version
ContentType
const ContentType = proto.ContentType
Record
const Record = @import("record.zig").Record
cert
const cert = common.cert
CertKeyPair
const CertKeyPair = common.CertKeyPair
W7Table
const W7Table = @import("crypto/ecdsa_p256.zig").W7Table
cipher_suites
const cipher_suites = @import("cipher.zig").cipher_suites
key_log
const key_log = @import("key_log.zig")
Client
const Client = @import("handshake_client.zig").Options
Server
const Server = @import("handshake_server.zig").Options
alpn
const alpn = @import("alpn.zig")
cipher_names
const cipher_names = @import("cipher_names.zig")
session_ticket
const session_ticket = @import("session_ticket.zig")
alpn
const alpn = @import("alpn.zig")
cipher_names
const cipher_names = @import("cipher_names.zig")
session_ticket
const session_ticket = @import("session_ticket.zig")
embed
const embed = @import("embed.zig")
ktls_linux
const ktls_linux = @import("ktls_linux.zig")
nonblock
const nonblock = struct
Non-blocking client/server handshake and connection. Handshake produces cipher used in connection to encrypt data for sending and decrypt received data.
Client
const Client = @import("handshake_client.zig").NonBlock
Server
const Server = @import("handshake_server.zig").NonBlock
Connection
const Connection = @import("connection.zig").NonBlock
Ktls
const Ktls = @import("Ktls.zig")
aes_gcm_cached
const aes_gcm_cached = @import("aes_gcm_cached.zig")
tls_hkdf
const tls_hkdf = @import("tls_hkdf.zig")
x25519_base
const x25519_base = @import("crypto/x25519_base.zig")
fuzz
const fuzz = struct
libFuzzer / audit hooks for untrusted handshake bytes (no panics).
parseClientHello
const parseClientHello = @import("handshake_server.zig").Handshake.fuzzReadClientHello
parseServerHello
const parseServerHello = @import("handshake_client.zig").Handshake.fuzzParseServerHello
max_ciphertext_record_len
encrypt_overhead_tls_12
const encrypt_overhead_tls_12: comptime_int = @max(
encrypt_overhead_tls_13
const encrypt_overhead_tls_13: comptime_int = @max(
max_cleartext_len
const max_cleartext_len = 1 << 14
max_ciphertext_len
const max_ciphertext_len = max_cleartext_len + 256
max_ciphertext_record_len
const max_ciphertext_record_len = record.header_len + max_ciphertext_len
max_certificate_msg_len
const max_certificate_msg_len = max_cleartext_len
Room for a Certificate handshake message carrying a real chain.
A single self-signed leaf fits in a few hundred bytes, which is why a small
buffer survives every test that uses one. A chain issued by a public CA does
not: a Let's Encrypt leaf plus its intermediate is several KB of DER, and
anything with a cross-signed root is larger again. Sizing this for the
convenient case makes the handshake fail against exactly the certificates
people deploy, with error.OutputBufferUndersize and no hint that the
certificate is the reason.
A record's cleartext limit is the natural bound: a message longer than this has to be fragmented across records regardless of buffer size.
max_handshake_flight_len
const max_handshake_flight_len = max_cleartext_len
Room for a whole server flight: EncryptedExtensions, an optional CertificateRequest, Certificate, CertificateVerify and Finished. The certificate dominates it, so this has to scale with the same bound rather than assume a small one.
max_encrypted_record_len
const max_encrypted_record_len = max_cleartext_len + @max(encrypt_overhead_tls_13, encrypt_overhead_tls_12)
Cipher
const Cipher = union(CipherSuite)
Provides initialization and common encrypt/decrypt methods for all supported ciphers. Tls 1.2 has only application cipher, tls 1.3 has separate cipher for handshake and application.
initTls12
fn initTls12(tag: CipherSuite, key_material: []const u8, side: proto.Side) !Cipher
initTls13
fn initTls13(tag: CipherSuite, secret: Transcript.Secret, side: proto.Side) !Cipher
encrypt
fn encrypt(
decrypt
fn decrypt(
decryptRecordInPlace
fn decryptRecordInPlace(c: *Cipher, record_buf: []u8) ![]const u8
TLS 1.3 application record decrypt with in-place payload (see Aead13Type.decryptRecordInPlace).
encryptApplication
fn encryptApplication(c: *Cipher, buf: []u8, cleartext_len: usize) !usize
Encrypt TLS 1.3 application data with cleartext already at buf[record.header_len..][0..cleartext_len].
transferApplication
fn transferApplication(
Encrypt then decrypt one TLS 1.3 application record (hot transfer path).
recordLen
fn recordLen(c: Cipher, cleartext_len: usize) usize
encryptOverhead
fn encryptOverhead(c: Cipher) usize
encryptSeq
fn encryptSeq(c: Cipher) u64
keyUpdateEncrypt
fn keyUpdateEncrypt(c: *Cipher) !void
keyUpdateDecrypt
fn keyUpdateDecrypt(c: *Cipher) !void
encrypt
fn encrypt(
Returns encrypted tls record in format: ----------------- buf ---------------------- header | explicit_iv | ciphertext | auth_tag
tls record header: 5 bytes explicit_iv: 8 bytes ciphertext: same length as cleartext auth_tag: 16 bytes
recordLen
fn recordLen(_: Self, cleartext_len: usize) usize
decrypt
fn decrypt(
Decrypts payload into cleartext. Returns tls record content type and cleartext. Accepts tls record header and payload: header | ----------- payload --------------- header | explicit_iv | ciphertext | auth_tag
encrypt
fn encrypt(
Returns encrypted tls record in format: ------------ buf ------------- header | ciphertext | auth_tag
tls record header: 5 bytes ciphertext: same length as cleartext auth_tag: 16 bytes
recordLen
fn recordLen(_: Self, cleartext_len: usize) usize
decrypt
fn decrypt(
Decrypts payload into cleartext. Returns tls record content type and cleartext. Accepts tls record header and payload: header | ----- payload ------- header | ciphertext | auth_tag
init
fn init(secret: Transcript.Secret, side: proto.Side) Self
refreshGcm
fn refreshGcm(self: *Self) void
keyUpdateEncrypt
fn keyUpdateEncrypt(self: *Self) void
keyUpdateDecrypt
fn keyUpdateDecrypt(self: *Self) void
encrypt
fn encrypt(
Returns encrypted tls record in format: ------------ buf ------------- header | ciphertext | auth_tag
tls record header: 5 bytes ciphertext: cleartext len + 1 byte content type auth_tag: 16 bytes
recordLen
fn recordLen(_: Self, cleartext_len: usize) usize
encryptApplication
fn encryptApplication(self: *Self, buf: []u8, cleartext_len: usize) !usize
Encrypt TLS 1.3 application data with cleartext already at buf[record.header_len..][0..cleartext_len].
decrypt
fn decrypt(
Decrypts payload into cleartext. Returns tls record content type and cleartext. Accepts tls record header and payload: header | ------- payload --------- header | ciphertext | auth_tag header | cleartext + ct | auth_tag Ciphertext after decryption contains cleartext and content type (1 byte).
decryptRecordInPlace
fn decryptRecordInPlace(self: *Self, record_buf: []u8) ![]const u8
Decrypt a full TLS 1.3 record buffer in place (header + payload).
encrypt
fn encrypt(
Returns encrypted tls record in format: ----------------- buf ----------------- header | iv | ------ ciphertext ------- header | iv | cleartext | mac | padding
tls record header: 5 bytes iv: 16 bytes ciphertext: cleartext length + mac + padding mac: 20, 32 or 48 (sha1, sha256, sha384) padding: 1-16 bytes
Max encrypt buf overhead = iv + mac + padding (1-16) aes_128_cbc_sha => 16 + 20 + 16 = 52 aes_128_cbc_sha256 => 16 + 32 + 16 = 64 aes_256_cbc_sha384 => 16 + 48 + 16 = 80
recordLen
fn recordLen(_: Self, cleartext_len: usize) usize
decrypt
fn decrypt(
Decrypts payload into cleartext. Returns tls record content type and cleartext.
additional_data_len
const additional_data_len = record.header_len + @sizeOf(u64)
cipher_suites
const cipher_suites = struct
tls12_secure
const tls12_secure = if (crypto.core.aes.has_hardware_support) [_]CipherSuite
tls12_weak
const tls12_weak = [_]CipherSuite
tls13_
const tls13_ = if (crypto.core.aes.has_hardware_support) [_]CipherSuite
tls13
const tls13 = &tls13_
tls12
const tls12 = &(tls12_secure ++ tls12_weak)
secure
const secure = &(tls13_ ++ tls12_secure)
all
const all = &(tls13_ ++ tls12_secure ++ tls12_weak)
includes
fn includes(list: []const CipherSuite, cs: CipherSuite) bool
CipherSuite
const CipherSuite = enum(u16)
validate
fn validate(cs: CipherSuite) !void
Versions
const Versions = enum
versions
fn versions(list: []const CipherSuite) !Versions
KeyExchangeAlgorithm
const KeyExchangeAlgorithm = enum
keyExchange
fn keyExchange(s: CipherSuite) KeyExchangeAlgorithm
HashTag
const HashTag = enum
hash
fn hash(cs: CipherSuite) HashTag
uniformHashTag
fn uniformHashTag(list: []const CipherSuite) ?HashTag
When every offered suite uses the same handshake hash, return it.
testCiphers
fn testCiphers() struct
Pair of ciphers based on keys from well-known key/iv pairs
Connection
Connection
const Connection = struct
enableKtls
fn enableKtls(c: *Self, fd: std.posix.socket_t) !void
Enable kernel TLS offload on fd after handshake completes.
Falls back to userspace crypto on non-Linux or unsupported ciphers.
ktlsEnabled
fn ktlsEnabled(c: Self) bool
sendNewSessionTicket
fn sendNewSessionTicket(c: *Self, ticket: session_ticket.Ticket) !void
Send a TLS 1.3 NewSessionTicket post-handshake message (server only).
next
fn next(c: *Self) anyerror!?[]const u8
Returns next record of cleartext data. Null on end of stream. Can be used in iterator like loop without memcpy to another buffer: while (try client.next()) |buf| { ... }
eof
fn eof(c: *Self) bool
close
fn close(c: *Self) anyerror!void
write
fn write(c: *Self, bytes: []const u8) !usize
Encrypts cleartext and writes it to the underlying stream as single tls record. Max single tls record payload length is 1<<14 (16K) bytes.
writeAll
fn writeAll(c: *Self, bytes: []const u8) !void
Encrypts cleartext and writes it to the underlying stream. If needed splits cleartext into multiple tls record.
read
fn read(c: *Self, buffer: []u8) !usize
readAll
fn readAll(c: *Self, buffer: []u8) !usize
Returns the number of bytes read. If the number read is smaller than
buffer.len, it means the stream reached the end.
readAtLeast
fn readAtLeast(c: *Self, buffer: []u8, len: usize) !usize
Returns the number of bytes read, calling the underlying read function
the minimal number of times until the buffer has at least len bytes
filled. If the number read is less than len it means the stream
reached the end.
readv
fn readv(c: *Self, iovecs: []std.posix.iovec) !usize
Returns the number of bytes read. If the number read is less than the space provided it means the stream reached the end.
Reader
const Reader = struct
init
fn init(c: *Connection, buffer: []u8) Reader
reader
fn reader(c: *Self, buffer: []u8) Reader
There is no strict requirement on buffer size. If the buffer is big enough tls record will be decrypted directly into provided buffer. If not input buffer will be used for record decryption and than cleartext will be copied to the reader buffer when needed.
Writer
const Writer = struct
init
fn init(c: *Connection, buffer: []u8) Writer
writer
fn writer(c: *Self, buffer: []u8) Writer
VecPut
const VecPut = struct
Abstraction for sending multiple byte buffers to a slice of iovecs.
put
fn put(vp: *VecPut, bytes: []const u8) usize
Returns the amount actually put which is always equal to bytes.len unless the vectors ran out of space.
NonBlock
const NonBlock = struct
init
fn init(c: Cipher) Self
encryptedLength
fn encryptedLength(self: Self, cleartext_len: usize) usize
Required ciphertext buffer length for the given cleartext length.
encrypt
fn encrypt(
Encrypts cleartext into ciphertext. If ciphertext.len is >= encryptedLength(cleartext.len) whole cleartext will be consumed.
decrypt
fn decrypt(
Decrypts ciphertext into cleartext. NOTE: It is safe to reuses ciphertext buffer for cleartext data.
close
fn close(self: *Self, ciphertext: []u8) ![]const u8
ecdsa_p256
nistz
const nistz = nistz_base
W7Table
const W7Table = nistz_base.W7Table
TableRows
const TableRows = nistz_base.TableRows
P256
const P256 = p256.P256
EcdsaP256Sha256
const EcdsaP256Sha256 = crypto.sign.ecdsa.Ecdsa(P256, crypto.hash.sha2.Sha256)
signCertificateVerifyTls
fn signCertificateVerifyTls(
CertificateVerify sign with cached private scalar (TLS 1.3 server hot path).
signPrehashed
fn signPrehashed(
Fast TLS CertificateVerify sign: nistz mulBase, x-only affine, var-time scalar invert.
verifyPrehashed
fn verifyPrehashed(
Verify a prehashed message using Shamir double-base mul (u1G + u2Q).
signatureToDerTls
fn signatureToDerTls(sig: Signature, buf: *[Signature.der_encoded_length_max]u8) []const u8
Encode a TLS CertificateVerify ECDSA-P256 signature (fixed 72-byte layout when canonical).
signatureFromDerTls
fn signatureFromDerTls(der: []const u8) EncodingError!Signature
Parse a TLS CertificateVerify ECDSA-P256 signature without the generic DER reader.
rsa
max_modulus_bits
const max_modulus_bits = 4096
ValueError
const ValueError = error
PublicKey
const PublicKey = struct
FromBytesError
const FromBytesError = ValueError || ff.OverflowError || ff.FieldElementError || ff.InvalidModulusError || error
fromBytes
fn fromBytes(mod: []const u8, exp: []const u8) FromBytesError!PublicKey
fromDer
fn fromDer(bytes: []const u8) (der.Parser.Error || FromBytesError)!PublicKey
fromSpki
fn fromSpki(bytes: []const u8) (der.Parser.Error || FromBytesError)!PublicKey
Parse an RSA public key from a DER-encoded SubjectPublicKeyInfo
(the format used by X.509 certificates, OpenSSL -pubout, and DKIM
p= records). Unwraps the AlgorithmIdentifier + BIT STRING and
parses the inner PKCS#1 RSAPublicKey.
encryptPkcsv1_5
fn encryptPkcsv1_5(pk: PublicKey, msg: []const u8, out: []u8) ![]const u8
Deprecated.
Encrypt a short message using RSAES-PKCS1-v1_5. The use of this scheme for encrypting an arbitrary message, as opposed to a randomly generated key, is NOT RECOMMENDED.
encryptOaep
fn encryptOaep(
Encrypt a short message using Optimal Asymmetric Encryption Padding (RSAES-OAEP).
byteLen
fn byteLen(bits: usize) usize
SecretKey
const SecretKey = struct
FromBytesError
const FromBytesError = ValueError || ff.OverflowError || ff.FieldElementError
fromBytes
fn fromBytes(n: Modulus, exp: []const u8) FromBytesError!SecretKey
KeyPair
const KeyPair = struct
FromDerError
const FromDerError = PublicKey.FromBytesError || SecretKey.FromBytesError || der.Parser.Error || error
fromDer
fn fromDer(bytes: []const u8) FromDerError!KeyPair
signPkcsv1_5
fn signPkcsv1_5(kp: KeyPair, comptime Hash: type, msg: []const u8, out: []u8) !PKCS1v1_5(Hash).Signature
Deprecated.
signerPkcsv1_5
fn signerPkcsv1_5(kp: KeyPair, comptime Hash: type) !PKCS1v1_5(Hash).Signer
Deprecated.
decryptPkcsv1_5
fn decryptPkcsv1_5(kp: KeyPair, ciphertext: []const u8, out: []u8) ![]const u8
Deprecated.
signOaep
fn signOaep(
signerOaep
fn signerOaep(kp: KeyPair, comptime Hash: type, salt: ?[]const u8) !Pss(Hash).Signer
Salt must outlive returned PSS.Signer.
decryptOaep
fn decryptOaep(
encrypt
fn encrypt(kp: KeyPair, plaintext: []const u8, out: []u8) !void
Encrypt short plaintext with secret key.
PKCS1v1_5
fn PKCS1v1_5(comptime Hash: type) type
Deprecated.
Signature Scheme with Appendix v1.5 (RSASSA-PKCS1-v1_5)
This standard has been superceded by PSS which is formally proven secure and has fewer footguns.
Signature
const Signature = struct
verifier
fn verifier(self: Self, public_key: PublicKey) !Verifier
verify
fn verify(self: Self, msg: []const u8, public_key: PublicKey) !void
Signer
const Signer = struct
update
fn update(self: *Signer, data: []const u8) void
finalize
fn finalize(self: *Signer, out: []u8) !PkcsT.Signature
Verifier
const Verifier = struct
update
fn update(self: *Verifier, data: []const u8) void
verify
fn verify(self: *Verifier) !void
Pss
fn Pss(comptime Hash: type) type
Probabilistic Signature Scheme (RSASSA-PSS)
Signature
const Signature = struct
verifier
fn verifier(self: Self, public_key: PublicKey) !Verifier
verify
fn verify(self: Self, msg: []const u8, public_key: PublicKey, salt_len: ?usize) !void
Signer
const Signer = struct
update
fn update(self: *Signer, data: []const u8) void
finalize
fn finalize(self: *Signer, out: []u8) !PssT.Signature
Verifier
const Verifier = struct
update
fn update(self: *Verifier, data: []const u8) void
verify
fn verify(self: *Verifier) !void
Record
header_len
const header_len = 5
Record
const Record = struct
init
fn init(buffer: []const u8) Record
read
fn read(rdr: *Io.Reader) Error!Record
decoder
fn decoder(rdr: *Io.Reader) !Decoder
Decoder
const Decoder = struct
init
fn init(content_type: proto.ContentType, payload: []const u8) Decoder
decode
fn decode(d: *Decoder, comptime T: type) !T
array
fn array(d: *Decoder, comptime len: usize) ![len]u8
slice
fn slice(d: *Decoder, len: usize) ![]const u8
skip
fn skip(d: *Decoder, amt: usize) !void
rest
fn rest(d: Decoder) []const u8
eof
fn eof(d: Decoder) bool
expectContentType
fn expectContentType(d: *Decoder, content_type: proto.ContentType) !void
raiseAlert
fn raiseAlert(d: *Decoder) !void
Writer
const Writer = struct
initFromIo
fn initFromIo(io_w: *Io.Writer) Writer
init
fn init(buffer: []u8) Writer
buffered
fn buffered(w: Writer) []const u8
bytesWritten
fn bytesWritten(w: Writer) usize
pos
fn pos(w: Writer) usize
byte
fn byte(w: *Writer, b: u8) !void
slice
fn slice(w: *Writer, bytes: []const u8) !void
int
fn int(w: *Writer, comptime T: type, value: anytype) !void
writableArray
fn writableArray(w: *Writer, comptime len: usize) !*[len]u8
enumValue
fn enumValue(w: *Writer, value: anytype) !void
enumList
fn enumList(w: *Writer, comptime E: type, tags: []const E) !void
extension
fn extension(w: *Writer, ex: proto.Extension, tags: anytype) !void
Default extension writer, writes extension type and list of tags
keyShare
fn keyShare(w: *Writer, named_groups: []const proto.NamedGroup, keys: []const []const u8) !void
Key share extension
serverName
fn serverName(w: *Writer, host: []const u8) !void
Server name extension
preSharedKey
fn preSharedKey(
Writes header of the pre shared key extension, without binders
preSharedKeyBinder
fn preSharedKeyBinder(w: *Writer, binder: []const u8) !void
Writes the rest of the pre shared keys extension
record
fn record(w: *Writer, content_type: proto.ContentType, payload: []const u8) !void
tls record
recordHeader
fn recordHeader(w: *Writer, content_type: proto.ContentType, payload_len: usize) !void
handshakeRecord
fn handshakeRecord(w: *Writer, handshake_type: proto.Handshake, payload: []const u8) !void
tls handshake record
handshakeRecordHeader
fn handshakeRecordHeader(w: *Writer, handshake_type: proto.Handshake, payload_len: usize) !void
unused
fn unused(w: *Writer) []u8
advance
fn advance(w: *Writer, n: usize) void
skip
fn skip(w: *Writer, n: usize) !usize
Skip n bytes from current position and return position before skip.
Used with writerAt to later return to that point and write skipped
bytes.
writerAt
fn writerAt(w: *Writer, p: usize) Writer
Returns writer at some previous position Parent buffer position is not changed.
writerAdvance
fn writerAdvance(w: *Writer, n: usize) !Writer
Returns new writer in unused buffer part advancing n bytes.
Parent buffer position is not changed.
header
fn header(content_type: proto.ContentType, payload_len: usize) [header_len]u8
handshakeHeader
fn handshakeHeader(handshake_type: proto.Handshake, payload_len: usize) [4]u8
proto
Version
const Version = enum(u16)
ContentType
const ContentType = enum(u8)
Handshake
const Handshake = enum(u8)
Curve
const Curve = enum(u8)
KeyExchangeModes
const KeyExchangeModes = enum(u8)
Extension
const Extension = enum(u16)
alertFromError
fn alertFromError(err: anyerror) [2]u8
Alert
const Alert = enum(u8)
Level
const Level = enum(u8)
Error
const Error = error
toError
fn toError(alert: Alert) Error!void
fromError
fn fromError(err: anyerror) Alert
parse
fn parse(buf: [2]u8) Alert
closeNotify
fn closeNotify() [2]u8
SignatureScheme
const SignatureScheme = enum(u16)
NamedGroup
const NamedGroup = enum(u16)
KeyUpdateRequest
const KeyUpdateRequest = enum(u8)
Side
const Side = enum
PrivateKey
fromFile
fn fromFile(_: Allocator, file: std.Io.File) !PrivateKey
parsePem
fn parsePem(buf: []const u8) !PrivateKey
parseDer
fn parseDer(buf: []const u8) !PrivateKey
parseEcDer
fn parseEcDer(bytes: []const u8) !PrivateKey
key_log
label
const label = struct
client_handshake_traffic_secret
const client_handshake_traffic_secret: []const u8 = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
server_handshake_traffic_secret
const server_handshake_traffic_secret: []const u8 = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
client_traffic_secret_0
const client_traffic_secret_0: []const u8 = "CLIENT_TRAFFIC_SECRET_0"
server_traffic_secret_0
const server_traffic_secret_0: []const u8 = "SERVER_TRAFFIC_SECRET_0"
client_random
const client_random: []const u8 = "CLIENT_RANDOM"
Callback
const Callback = *const fn (label: []const u8, client_random: []const u8, secret: []const u8) void
callback
fn callback(label_: []const u8, client_random: []const u8, secret: []const u8) void
Writes tls keys to the file pointed by SSLKEYLOGFILE environment variable.
fileAppend
fn fileAppend(file_name: []const u8, label_: []const u8, client_random: []const u8, secret: []const u8) !void
formatLine
fn formatLine(buf: []u8, label_: []const u8, client_random: []const u8, secret: []const u8) ![]const u8
Client
info
fn info(comptime _: []const u8, _: anytype) void
err
fn err(comptime _: []const u8, _: anytype) void
warn
fn warn(comptime _: []const u8, _: anytype) void
debug
fn debug(comptime _: []const u8, _: anytype) void
Options
const Options = struct
Diagnostic
const Diagnostic = struct
SessionResumption
const SessionResumption = struct
Collects and stores session resumption tickets.
Ticket
const Ticket = struct
init
fn init(payload: []const u8, secret: []const u8) !Ticket
obfuscatedAge
fn obfuscatedAge(t: Ticket) u32
Obfuscated age for pre shared extension in client hello message when using this ticket.
init
fn init(allocator: mem.Allocator) Self
appendSecret
fn appendSecret(self: *Self, tag: CipherSuite.HashTag, secret: []const u8) !usize
Set resumption master secret (known at then end of the handshake) to be used by new session ticket's sent on that connection. Returns index of the appended secret in the secrets list. Connection should use that index in pushTicket to connect ticket and the secret.
pushTicket
fn pushTicket(self: *Self, data: []const u8, secret_idx: usize) !void
When new session ticket message is recived connection should push ticket.
popTicket
fn popTicket(self: *Self) ?Ticket
deinit
fn deinit(self: *Self) void
print
fn print(self: Self) !void
Handshake
const Handshake = struct
Handshake parses tls server message and creates client messages. Collects tls attributes: server random, cipher suite and so on. Client messages are created using provided buffer. Provided record reader is used to get tls record when needed.
handshake
fn handshake(h: *Self, opt: Options) !struct
Handshake exchanges messages with server to get agreement about cryptographic parameters. That upgrades existing client-server connection to TLS connection. Returns cipher used in application for encrypted message exchange.
Handles TLS 1.2 and TLS 1.3 connections. After initial client hello server chooses in its server hello which TLS version will be used.
TLS 1.2 handshake messages exchange: Client Server
ClientHello client flight 1 ---> ServerHello Certificate ServerKeyExchange CertificateRequest* <--- server flight 1 ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* ChangeCipherSpec Finished client flight 2 ---> ChangeCipherSpec <--- server flight 2 Finished
TLS 1.3 handshake messages exchange: Client Server
ClientHello client flight 1 ---> ServerHello {EncryptedExtensions} {CertificateRequest*} {Certificate} {CertificateVerify} <--- server flight 1 {Finished} ChangeCipherSpec {Certificate*} {CertificateVerify*} Finished client flight 2 --->
-
- optional {} - encrypted
References: https://datatracker.ietf.org/doc/html/rfc5246#section-7.3 https://datatracker.ietf.org/doc/html/rfc8446#section-2
fuzzParseServerHello
fn fuzzParseServerHello(payload: []const u8) void
Fuzz/audit entry: parse untrusted ServerHello bytes without panicking.
NonBlock
const NonBlock = struct
init
fn init(opt: Options) Self
deinit
fn deinit(self: *Self) void
Release any heap state owned by the handshake (the optional P-256 verify
table allocated from opt.table_allocator). No-op when table_allocator
is unset. Call once when the client is no longer needed.
reset
fn reset(self: *Self) void
Start a new handshake reusing opt and any cached certificate state.
done
fn done(self: Self) bool
True when handshake is successfully finished
run
fn run(
Runs next handshake step.
cipher
fn cipher(self: Self) ?Cipher
Cipher produced in handshake, null until successful handshake.
selectedAlpn
fn selectedAlpn(self: Self) ?alpn.Protocol
Negotiated ALPN protocol, available after handshake completes.
Server
info
fn info(comptime _: []const u8, _: anytype) void
err
fn err(comptime _: []const u8, _: anytype) void
warn
fn warn(comptime _: []const u8, _: anytype) void
debug
fn debug(comptime _: []const u8, _: anytype) void
Options
const Options = struct
SNICallback
const SNICallback = *const fn (
SessionTickets
const SessionTickets = struct
effectiveNamedGroups
fn effectiveNamedGroups(self: Options) []const proto.NamedGroup
ClientAuth
const ClientAuth = struct
Type
const Type = enum
Handshake
const Handshake = struct
earlyData
fn earlyData(h: Self) []const u8
handshake
fn handshake(h: *Self, opt_in: Options) !Cipher
selectedAlpnProtocol
fn selectedAlpnProtocol(h: Self) ?alpn.Protocol
issueSessionTicket
fn issueSessionTicket(h: *Self, opt: Options, allocator: mem.Allocator) !?session_ticket.Ticket
fuzzReadClientHello
fn fuzzReadClientHello(payload: []const u8) void
Fuzz/audit entry: parse untrusted ClientHello bytes without panicking.
NonBlock
const NonBlock = struct
init
fn init(opt: Options) Self
reset
fn reset(self: *Self) void
Start a new handshake reusing opt (bench / session resumption helpers).
done
fn done(self: Self) bool
True when handshake is successfully finished
run
fn run(
Runs next handshake step.
cipher
fn cipher(self: Self) ?Cipher
Cipher produced in handshake, null until successful handshake.
selectedAlpn
fn selectedAlpn(self: Self) ?alpn.Protocol
Negotiated ALPN protocol, available after handshake completes.
earlyData
fn earlyData(self: Self) []const u8
0-RTT early data received from the client (empty if none).
alpn
Protocol
const Protocol = []const u8
ProtocolList
const ProtocolList = []const Protocol
negotiate
fn negotiate(client_protocols: ProtocolList, server_protocols: ProtocolList) ?Protocol
Select the first client protocol that appears in the server list (RFC 7301).
Callback
const Callback = *const fn (
Per-connection ALPN picker (Node ALPNCallback semantics).
negotiateWithCallback
fn negotiateWithCallback(
parseProtocolListFixed
fn parseProtocolListFixed(
Parse ALPN extension payload into caller-provided protocol pointer array.
Protocol name bytes are views into payload.
parseProtocolList
fn parseProtocolList(allocator: mem.Allocator, payload: []const u8) ![]const Protocol
Parse ALPN extension payload into a slice of protocol name views.
writeExtension
fn writeExtension(w: *record.Writer, protocols: ProtocolList) !void
Write ALPN extension to a record Writer.
makeEncryptedExtensionsBody
fn makeEncryptedExtensionsBody(buf: []u8, selected: ?Protocol) ![]const u8
Build encrypted_extensions body with optional ALPN selected protocol.
cipher_names
opensslName
fn opensslName(cs: CipherSuite) ?[]const u8
OpenSSL / IANA cipher suite name for each supported suite.
parseCipherList
fn parseCipherList(allocator: mem.Allocator, ciphers: []const u8) ![]CipherSuite
Parse an OpenSSL-style colon-separated cipher list into preference-ordered suites.
Supports @SECLEVEL=n prefix (ignored for ordering; suites still filtered by grade).
fromOpensslName
fn fromOpensslName(name: []const u8) ?CipherSuite
Look up a cipher suite by OpenSSL name (case-sensitive).
validNames
fn validNames(allocator: mem.Allocator) ![]const []const u8
Return all valid OpenSSL cipher names for validation (e.g. Bun validateCiphers).
session_ticket
TicketKeys
const TicketKeys = struct
48-byte ticket keys per Node.js / OpenSSL convention: 16-byte name prefix, 16-byte HMAC key, 16-byte AES key.
fromBytes
fn fromBytes(bytes: *const [48]u8) TicketKeys
random
fn random() TicketKeys
TicketKeyRing
const TicketKeyRing = struct
Thread-safe bounded session-ticket key ring.
New tickets always use the active key at index zero. Resumption accepts the active key and at most three previous keys. Keep the ring at a stable address for as long as server configurations reference it. Rotation is serialized, does not require a listener restart, and securely clears retired material.
capacity
const capacity = 4
init
fn init(primary: TicketKeys) TicketKeyRing
rotate
fn rotate(self: *TicketKeyRing, next: TicketKeys) error
active
fn active(self: *TicketKeyRing) TicketKeys
decryptTicket
fn decryptTicket(self: *TicketKeyRing, identity: []const u8) ?SessionState
keyCount
fn keyCount(self: *TicketKeyRing) usize
containsKeyName
fn containsKeyName(self: *TicketKeyRing, name: *const [16]u8) bool
SessionState
const SessionState = struct
Serialized session state encrypted into a TLS session ticket.
Ticket
const Ticket = struct
encrypt
fn encrypt(
Encrypt session state into a ticket identity blob.
decrypt
fn decrypt(identity: []const u8, keys: TicketKeys) ?SessionState
Decrypt a ticket identity blob. Returns null if keys don't match or decryption fails.
makeNewSessionTicket
fn makeNewSessionTicket(
Build a TLS 1.3 NewSessionTicket handshake message body.
NewSessionCallback
const NewSessionCallback = *const fn (
Called when a new session is established (Node newSession callback).
ResumeSessionCallback
const ResumeSessionCallback = *const fn (
Called when client offers a ticket (Node resumeSession callback).
Manager
const Manager = struct
Server-side session ticket manager.
init
fn init(keys: TicketKeys) Manager
initKeyRing
fn initKeyRing(key_ring: *TicketKeyRing) Manager
nextNonce
fn nextNonce(self: *Manager) []const u8
issueTicket
fn issueTicket(
resumeTicket
fn resumeTicket(self: *Manager, identity: []const u8) ?SessionState
embed
Error
const Error = enum(c_int)
Mode
const Mode = enum(c_int)
Context
const Context = struct
Connection
const Connection = struct
ktls_linux
Error
const Error = error
enable
fn enable(fd: posix.socket_t, ktls: Ktls) Error!void
isSupported
fn isSupported(cipher: @import("cipher.zig").Cipher) bool
Ktls
txBytes
fn txBytes(k: *Ktls) []const u8
rxBytes
fn rxBytes(k: *Ktls) []const u8
VERSION_1_2
const VERSION_1_2 = 0x0303
VERSION_1_3
const VERSION_1_3 = 0x0304
TX
const TX = 1
RX
const RX = 2
AES_GCM_128
const AES_GCM_128 = 51
AES_GCM_256
const AES_GCM_256 = 52
CHACHA20_POLY1305
const CHACHA20_POLY1305 = 54
Info
const Info = extern struct
AesGcm128
const AesGcm128 = extern struct
AesGcm256
const AesGcm256 = extern struct
Chacha20Poly1305
const Chacha20Poly1305 = extern struct
init
fn init(cipher: Cipher) Ktls
aes_gcm_cached
CachedAesGcm
fn CachedAesGcm(comptime Aes: type) type
tag_length
const tag_length = 16
nonce_length
const nonce_length = 12
key_length
const key_length = Aes.key_bits / 8
fromKey
fn fromKey(key: [key_length]u8) @This()
encrypt
fn encrypt(
encryptTls13
fn encryptTls13(
TLS 1.3 record path: AD is always the 5-byte record header.
decrypt
fn decrypt(
decryptTls13
fn decryptTls13(
TLS 1.3 record path: AD is always the 5-byte record header.
tls_hkdf
expandLabelEmpty
fn expandLabelEmpty(
HKDF-Expand-Label with empty context (common for key/iv/finished labels).
x25519_base
recoverPublicKey
fn recoverPublicKey(seed: [32]u8) [32]u8
Compute the X25519 public key for seed (clamps internally).
Equivalent to std.crypto.dh.X25519.recoverPublicKey.