silk.tls.server.

A TLS 1.2 and TLS 1.3 server state machine that does the handshake and protects application data over a byte transport that you drive.

When to use#

Use Server to accept TLS connections, for example in an HTTPS server or a runtime's node:tls. Make one server for each accepted connection with Server.make, then move bytes between it and the transport until it reports HandshakeComplete, and then read and write application data.

Details#

The server accepts the versions that ServerConfig.versions allows, and prefers TLS 1.3. In TLS 1.3 it selects the first cipher suite in the client's order among ChaCha20-Poly1305, AES-128-GCM, and AES-256-GCM. It selects the key exchange group from X25519, P-256, and P-384 in that order, limited by your GroupPolicy. If the client sent no key share for an allowed group that it supports, the server sends one HelloRetryRequest. The server signs CertificateVerify with the leaf's ECDSA P-256, ECDSA P-384, Ed25519, or RSA key (SigningKey), using a scheme that the client offers, and checks the client's Finished message. An RSA key signs with RSA-PSS, preferring SHA-256, then SHA-384, then SHA-512.

The server reads the client's SNI name, which you get from Server.serverName, and selects an ALPN protocol from your AlpnConfig in your preference order. It handles KeyUpdate in both directions, close_notify, and the compatibility change_cipher_spec records.

In TLS 1.2 (RFC 5246), the server selects the first ECDHE suite in the client's order that its key can sign for: ECDSA keys take the ECDSA suites and RSA keys take the RSA suites, each with ChaCha20-Poly1305, AES-128-GCM, or AES-256-GCM. An Ed25519 key serves no TLS 1.2 suite. The server requires the extended master secret (RFC 7627), and an ECDSA certificate's curve must be in the client's groups. When TLS 1.3 is also allowed, it puts the RFC 8446 downgrade mark in a TLS 1.2 ServerHello.

Each call returns a ServerProgress: how many bytes it took or wrote, and the next ServerDemand. Output works in two steps: write Server.pendingOutput to the transport, and then call Server.ackWritten with the number of bytes written. During the handshake, the server takes no input while output is pending. ServerLimits bound all memory and work.

Errors#

  • ServerError for a configuration that is not valid, an alert from the client, a protocol error, no shared parameters, a client certificate that ClientAuth rejects, a limit, or a call in the wrong state. An error from a call after Server.make is permanent for the server.

  • OutOfMemoryError if the Allocator fails.

With ClientAuth Request, the server sends a CertificateRequest, checks the client's CertificateVerify with its leaf's key, and validates the client's chain against your trust anchors for the ClientAuth purpose. In TLS 1.2 the request lists no certificate authorities, and the client may sign with ECDSA or RSA under SHA-256 or SHA-384. Server.clientCertificateStatus and Server.clientCertificates tell you the result.

With TicketPolicy Issue, the server sends NewSessionTicket messages after the client's Finished, when the client offered psk_dhe_ke. Each ticket holds the session state sealed with AES-256-GCM under your TicketKey, so the server keeps no session cache. A ClientHello that offers a valid ticket resumes: the server checks the binder, sends no certificate messages, and Server.resumed returns true. A ticket from a handshake whose client certificate the current ClientAuth would refuse gives a full handshake instead.

In TLS 1.2 the server issues one ticket (RFC 5077) when the client sends a session_ticket extension: a NewSessionTicket before its ChangeCipherSpec, with the TicketPolicy lifetime as the hint. A ClientHello with a session ID and a valid ticket of the same cipher suite resumes: the server echoes the session ID and sends its ChangeCipherSpec and Finished right after the ServerHello, with no new ticket. The server keeps no session cache, so it never resumes by session ID alone, and its full handshakes send an empty session ID.

When the TicketPolicy maxEarlyData is not 0, the tickets allow 0-RTT data. The server accepts a resuming client's early data when the ticket allows it, there was no HelloRetryRequest, the cipher suite and ALPN protocol are the ones of the session, and the client's ticket age is within 10 seconds of the server's. It then reports PlaintextReady before HandshakeComplete, and Server.earlyData returns Accepted. Otherwise it skips the early data, up to ServerLimits rejectedEarlyDataBytes.

The server keeps no state across connections, so it cannot detect a replayed ClientHello. An attacker can deliver the same early data many times. Accept 0-RTT data only for requests that are safe to repeat.

Gotchas#

The server resumes only sessions from its own tickets, and only with (EC)DHE. The ticket checks use the TicketPolicy now, so make a server with the current time. It does not ask for ed25519 client signatures, because the certificate profile admits no Ed25519 client keys. The server sends no alert when it fails, so close the transport. Dropping the server does not send close_notify. Call Server.closeWrite first. Secrets are not erased.

Examples#

Reject a configuration without certificates#

silk
import silk.mem.allocator { Allocator, OutOfMemoryError }
import silk.core.effect { Effect }
import silk.system.random { Random }
import silk.core.result { Result }
import silk.crypto.p256 { P256 }
import silk.tls.client { AlpnConfig }
import silk.tls.certificate { CertificateDer }
import silk.tls.signature { SigningKey }
import silk.tls.record { VersionPolicy }
import silk.tls.server {
  ClientAuth,
  GroupPolicy,
  Server,
  ServerConfig,
  ServerError,
  ServerLimits,
  TicketPolicy,
}
import silk.collections.slice { Slice }
import silk.num.usize

// Not secure. Real programs use a `Random` provider from the operating system.
struct ExampleRandom {
  next: usize,
}

impl Random for ExampleRandom {
  effect fn fillBytes(self: &mut Self, output: &mut [u8]) -> () {
    let mut index: usize = 0
    while index < output.length {
      output[index] = usize.toU8((self.next + index) % 251 + 1)
      index = index + 1
    }
    self.next = self.next + output.length
    return ()
  }
}

pub effect fn main() -> i32
  ! OutOfMemoryError {
  let mut allocator = Allocator.systemAllocatorProvider()
  let mut random = ExampleRandom { next: 1 }
  let key = run P256.generate() |> Effect.provideMut<Random>(&mut random)
  let chain: [CertificateDer<'static>; 0] = []
  let config = ServerConfig<'static> {
    certificates: Slice.view<CertificateDer<'static>>(&chain, 0, 0),
    alpn: AlpnConfig.defaults(),
    groups: GroupPolicy.defaults(),
    clientAuth: ClientAuth<'static>.Off,
    tickets: TicketPolicy<'static>.Off,
    versions: VersionPolicy.defaults(),
    limits: ServerLimits.defaults(),
  }
  let made = run Server.make(&config, SigningKey.EcdsaP256 { key: move key })
    |> Effect.provideMut<Allocator>(&mut allocator)
  return match move made {
    Result<Server, ServerError>.Success {..} => 1
    Result<Server, ServerError>.Failure { error: ServerError.EmptyCertificateChain } => 0
    Result<Server, ServerError>.Failure {..} => 1
  }
}

Import as Server with import silk.tls.server { Server }.

Public declarations: 16.

ServerGroup#

silk
pub enum ServerGroup

A key exchange group that the server can select.

X25519#

silk
X25519

X25519 with a 32-byte public key.

P256#

silk
P256

The NIST P-256 curve with a 65-byte uncompressed point.

P384#

silk
P384

The NIST P-384 curve with a 97-byte uncompressed point.

Implementation Debug for ServerGroup#

silk
impl Debug for ServerGroup

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as X25519.

GroupPolicy#

silk
pub struct GroupPolicy

The key exchange groups that the server allows. It prefers X25519, then P-256, then P-384.

Field x25519#

silk
pub x25519: bool

Allows X25519.

Field p256#

silk
pub p256: bool

Allows P-256.

Field p384#

silk
pub p384: bool

Allows P-384.

Implementation Copy for GroupPolicy#

silk
impl Copy for GroupPolicy

Implementation GroupPolicy#

silk
impl GroupPolicy

Associated function defaults#

silk
pub fn defaults() -> GroupPolicy

Returns the policy that allows all three groups.

ServerLimits#

silk
pub struct ServerLimits

Inclusive local resource policy for one server connection. The limits bound all memory and work of the server.

Field handshakeBodyBytes#

silk
pub handshakeBodyBytes: usize

Maximum body bytes in one handshake message from the client, from 64 to 16777215.

Field handshakeBytes#

silk
pub handshakeBytes: usize

Maximum total handshake bytes from the client, including four-byte headers.

Field handshakeMessages#

silk
pub handshakeMessages: usize

Maximum handshake message count from the client.

Field extensionBytes#

silk
pub extensionBytes: usize

Maximum bytes in one extension vector.

Field emptyRecords#

silk
pub emptyRecords: usize

Maximum consecutive empty application or compatibility records.

Field postHandshakeControls#

silk
pub postHandshakeControls: usize

Maximum consecutive post-handshake control messages without positive application content.

Field certificates#

silk
pub certificates: usize

Maximum certificate count in the configured chain, at most 16.

Field certificateBytes#

silk
pub certificateBytes: usize

Maximum aggregate DER bytes in the configured chain.

Field certificateDecode#

silk
pub certificateDecode: DecodeLimits

Strict decoder policy for the configured leaf certificate and each client certificate.

Field clientCertificates#

silk
pub clientCertificates: usize

Maximum certificate count in a client's chain, at most 16.

Field clientCertificateBytes#

silk
pub clientCertificateBytes: usize

Maximum aggregate DER bytes in a client's chain.

Field clientTrust#

silk
pub clientTrust: SnapshotLimits

Limits for the copy of ClientAuth's trust anchors.

Field clientValidation#

silk
pub clientValidation: ValidationLimits

Limits for validating a client's chain.

Field rejectedEarlyDataBytes#

silk
pub rejectedEarlyDataBytes: usize

Maximum protected record bytes of rejected 0-RTT data that the server skips. More fails with BadRecordMac.

Implementation Copy for ServerLimits#

silk
impl Copy for ServerLimits

Implementation ServerLimits#

silk
impl ServerLimits

Associated function defaults#

silk
pub fn defaults() -> ServerLimits

Returns the finite TLS server defaults.

ServerConfig#

silk
pub struct ServerConfig<'a>

Borrowed server configuration that Server.make copies into owned storage.

Field certificates#

silk
pub certificates: &'a [CertificateDer<'a>]

The certificate chain, leaf first. The leaf's public key matches the SigningKey.

Field alpn#

silk
pub alpn: AlpnConfig<'a>

The supported ALPN protocols in server preference order. required makes a client without ALPN fail.

Field groups#

silk
pub groups: GroupPolicy

The key exchange groups that the server allows.

Field clientAuth#

silk
pub clientAuth: ClientAuth<'a>

Whether the server asks for a client certificate, and how it checks one.

Field tickets#

silk
pub tickets: TicketPolicy<'a>

Whether the server issues session tickets and resumes sessions from them.

Field versions#

silk
pub versions: VersionPolicy

The TLS versions the server accepts. VersionPolicy.defaults() accepts TLS 1.2 and TLS 1.3.

Field limits#

silk
pub limits: ServerLimits

Finite connection limits.

TicketKey#

silk
pub struct TicketKey

The key that seals and opens session tickets, in TicketPolicy.

Details#

The 48 bytes are a 16-byte key name, which the server puts at the start of each ticket, and a 32-byte AES-256-GCM key. Servers that share a key resume each other's sessions.

Gotchas#

Anyone with the key can decrypt the session secrets of every ticket that it sealed. Make it with random bytes, keep it secret, and replace it often.

Implementation Copy for TicketKey#

silk
impl Copy for TicketKey

Implementation TicketKey#

silk
impl TicketKey

Associated function make#

silk
pub fn make(bytes: &[u8; 48]) -> TicketKey

Returns the key with the name bytes[0..16] and the AES-256-GCM key bytes[16..48].

TicketPolicy#

silk
pub union TicketPolicy<'a>

Whether a Server issues session tickets, in ServerConfig.tickets.

Off#

silk
Off

The server issues no tickets and does full handshakes only.

Issue#

silk
Issue

After the client's Finished, the server sends count NewSessionTicket messages sealed with key. A later ClientHello that offers one of them resumes the session without certificates, when the ticket is younger than lifetime at now, has the same server name, and has the same cipher suite hash.

Field key#

silk
pub key: &'a TicketKey

The key that seals and opens tickets.

Field now#

silk
pub now: &'a Instant

The current time, which dates new tickets and checks the age of offered ones.

Field lifetime#

silk
pub lifetime: usize

The ticket lifetime in seconds, from 1 to 604800.

Field count#

silk
pub count: usize

The number of tickets to send after each TLS 1.3 handshake, from 1 to 4. TLS 1.2 sends one.

Field maxEarlyData#

silk
pub maxEarlyData: usize

The most 0-RTT plaintext bytes that a client may send when it resumes from one of these tickets, at most 16777216, or 0 for none.

Implementation Copy for TicketPolicy<'a>#

silk
impl<'a> Copy for TicketPolicy<'a>

ClientAuth#

silk
pub union ClientAuth<'a>

Whether a Server asks the client for a certificate, in ServerConfig.clientAuth.

Off#

silk
Off

The server does not ask for a client certificate.

Request#

silk
Request

The server sends a CertificateRequest. When the client sends a chain, the server checks its CertificateVerify with the leaf's key, and validates the chain against trust at validationTime for the ClientAuth purpose.

Field trust#

silk
pub trust: &'a TrustSnapshot

The anchors that a client chain must lead to. Server.make copies them.

Field validationTime#

silk
pub validationTime: &'a Instant

The time at which certificate dates are checked.

Field required#

silk
pub required: bool

Whether a client that sends no certificate fails with ClientCertificateRequired.

Field rejectUntrusted#

silk
pub rejectUntrusted: bool

Whether a chain that does not validate fails with UntrustedClientCertificate. Otherwise the handshake completes, and Server.clientCertificateStatus gives Untrusted.

Implementation Copy for ClientAuth<'a>#

silk
impl<'a> Copy for ClientAuth<'a>

ClientCertificateStatus#

silk
pub union ClientCertificateStatus

What the server knows about the client's certificate, from Server.clientCertificateStatus.

NotRequested#

silk
NotRequested

The server does not ask for a client certificate.

Pending#

silk
Pending

The client has not sent its Certificate message yet.

Absent#

silk
Absent

The client sent no certificate.

Trusted#

silk
Trusted

The chain validated, and the client signed CertificateVerify with the leaf's key.

Untrusted#

silk
Untrusted

The client signed CertificateVerify with the leaf's key, but the chain did not validate.

Field error#

silk
pub error: ValidationError

Why the chain did not validate.

Resumed#

silk
Resumed

The connection resumed a session in which the client presented a certificate. The client sends no certificate on resumption, so Server.clientCertificates is empty.

Field trusted#

silk
pub trusted: bool

Whether the chain validated in the original handshake.

Implementation Debug for ClientCertificateStatus#

silk
impl Debug for ClientCertificateStatus

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant and its fields, such as Untrusted { ... }.

ServerDemand#

silk
pub enum ServerDemand

The next action or observable connection event of a Server, in ServerProgress.demand.

NeedInput#

silk
NeedInput

Supply client transport bytes.

NeedOutput#

silk
NeedOutput

Write and acknowledge the complete pending output before other work.

PlaintextReady#

silk
PlaintextReady

Read buffered application plaintext.

HandshakeComplete#

silk
HandshakeComplete

Observe the one-shot handshake completion. Application data can flow after it.

PeerClosed#

silk
PeerClosed

The client's direction closed cleanly.

Closed#

silk
Closed

Both directions closed cleanly and no output remains.

ServerProgress#

silk
pub struct ServerProgress

Exact progress from one Server operation: how many bytes it took or wrote, and the next ServerDemand.

Field consumed#

silk
pub consumed: usize

The accepted prefix of caller input or application plaintext.

Field written#

silk
pub written: usize

The bytes copied into a caller plaintext destination.

Field demand#

silk
pub demand: ServerDemand

The next action or event.

Implementation Copy for ServerProgress#

silk
impl Copy for ServerProgress

ServerOperation#

silk
pub enum ServerOperation

A public operation rejected because of caller state.

FeedInput#

silk
FeedInput

Transport input feed.

Progress#

silk
Progress

State-machine progress without new bytes.

AckWritten#

silk
AckWritten

Pending-output acknowledgment.

ReadPlaintext#

silk
ReadPlaintext

Application plaintext read.

WritePlaintext#

silk
WritePlaintext

Application plaintext write.

RequestKeyUpdate#

silk
RequestKeyUpdate

Local traffic-key update request.

CloseWrite#

silk
CloseWrite

Local write-direction close.

EndInput#

silk
EndInput

Transport input end.

Implementation Debug for ServerOperation#

silk
impl Debug for ServerOperation

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as FeedInput.

ServerProtocolReason#

silk
pub enum ServerProtocolReason

A protocol rule that the client broke.

Record#

silk
Record

A record has an invalid content type, version, length, padding, or inner framing.

UnexpectedMessage#

silk
UnexpectedMessage

A message or record arrived in an invalid order.

InvalidLength#

silk
InvalidLength

A handshake message or vector is truncated or has trailing bytes.

Extension#

silk
Extension

An extension is duplicated, misplaced, or malformed.

ClientHello#

silk
ClientHello

ClientHello has a field that TLS 1.3 forbids.

HelloRetryRequest#

silk
HelloRetryRequest

The second ClientHello does not follow the HelloRetryRequest.

CompatibilityCcs#

silk
CompatibilityCcs

A compatibility change_cipher_spec record is outside its window or not exactly {1}.

PostHandshake#

silk
PostHandshake

A KeyUpdate or other post-handshake message is not valid.

ClientCertificate#

silk
ClientCertificate

A client Certificate or CertificateVerify message has invalid framing.

InternalState#

silk
InternalState

The server reached an impossible private transition.

EarlyData#

silk
EarlyData

The client sent more 0-RTT data than the ticket allows, or misplaced EndOfEarlyData.

Implementation Debug for ServerProtocolReason#

silk
impl Debug for ServerProtocolReason

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as Record.

NegotiationFailure#

silk
pub enum NegotiationFailure

A handshake parameter that the client and the server do not share.

Version#

silk
Version

The client offers no TLS version that the server accepts.

CipherSuite#

silk
CipherSuite

The client offers no supported cipher suite.

Group#

silk
Group

The client supports no group that the GroupPolicy allows.

SignatureScheme#

silk
SignatureScheme

The client does not accept the signature scheme of the SigningKey.

ExtendedMasterSecret#

silk
ExtendedMasterSecret

A TLS 1.2 client does not offer the extended master secret (RFC 7627), which the server requires.

Implementation Debug for NegotiationFailure#

silk
impl Debug for NegotiationFailure

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as Version.

ServerLimitKind#

silk
pub enum ServerLimitKind

A named finite resource exhausted by client input or configuration.

HandshakeBodyBytes#

silk
HandshakeBodyBytes

One handshake body.

HandshakeBytes#

silk
HandshakeBytes

Aggregate handshake headers and bodies.

HandshakeMessages#

silk
HandshakeMessages

Handshake message count.

ExtensionBytes#

silk
ExtensionBytes

One extension vector.

EmptyRecords#

silk
EmptyRecords

Consecutive empty application or compatibility records.

PostHandshakeControls#

silk
PostHandshakeControls

Consecutive post-handshake control messages.

Certificates#

silk
Certificates

Configured certificate count.

CertificateBytes#

silk
CertificateBytes

Configured certificate DER bytes.

Alpn#

silk
Alpn

One ALPN protocol or list.

ClientCertificates#

silk
ClientCertificates

Client certificate count.

ClientCertificateBytes#

silk
ClientCertificateBytes

Client certificate DER bytes.

ClientTrust#

silk
ClientTrust

Trust anchors for client certificates.

Implementation Debug for ServerLimitKind#

silk
impl Debug for ServerLimitKind

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant, such as HandshakeBodyBytes.

ServerError#

silk
pub union ServerError

A typed TLS server failure. An error from a call after Server.make is permanent for the server.

EmptyCertificateChain#

silk
EmptyCertificateChain

The configured chain has no certificates.

CertificateDecode#

silk
CertificateDecode

The configured leaf certificate did not decode.

Field error#

silk
pub error: DecodeError

The complete strict decoder failure.

KeyMismatch#

silk
KeyMismatch

The configured leaf certificate's public key does not match the SigningKey.

PeerAlert#

silk
PeerAlert

The client sent a fatal alert with this wire description.

Field code#

silk
pub code: u8

The alert description byte.

BadRecordMac#

silk
BadRecordMac

Protected record authentication failed.

ProtocolViolation#

silk
ProtocolViolation

The client broke a protocol rule.

Field reason#

silk
pub reason: ServerProtocolReason

The rejected rule.

Negotiation#

silk
Negotiation

The client and the server share no value for a handshake parameter.

Field failure#

silk
pub failure: NegotiationFailure

The parameter without a shared value.

InvalidKeyShare#

silk
InvalidKeyShare

The client's key share is not a valid public key.

Signing#

silk
Signing

The key could not sign CertificateVerify, for example because an RSA key is too small for the scheme.

Field error#

silk
pub error: SigningError

The signing failure.

Finished#

silk
Finished

The client's Finished did not authenticate the transcript.

Binder#

silk
Binder

The client's PSK binder did not authenticate the ClientHello for a ticket that the server sealed.

InvalidTicketPolicy#

silk
InvalidTicketPolicy

TicketPolicy Issue has a lifetime, count, or maxEarlyData out of range.

LimitExceeded#

silk
LimitExceeded

A finite resource budget was exceeded.

Field kind#

silk
pub kind: ServerLimitKind

The exhausted resource category.

Field limit#

silk
pub limit: usize

The inclusive configured limit.

InvalidState#

silk
InvalidState

A caller operation is invalid in the current state.

Field operation#

silk
pub operation: ServerOperation

The rejected operation.

EmptyBuffer#

silk
EmptyBuffer

A caller supplied an empty plaintext output buffer.

HandshakeTruncated#

silk
HandshakeTruncated

Transport input ended before the handshake completed.

Truncated#

silk
Truncated

Transport input ended after the handshake without client close_notify.

NoApplicationProtocol#

silk
NoApplicationProtocol

The client's ALPN offer shares no protocol with the server, or the server requires ALPN and the client sent none.

ClientCertificateRequired#

silk
ClientCertificateRequired

The server requires a client certificate, and the client sent none.

ClientCertificateDecode#

silk
ClientCertificateDecode

A client certificate did not decode.

Field error#

silk
pub error: DecodeError

The decoder failure.

ClientCertificateVerify#

silk
ClientCertificateVerify

The client's CertificateVerify did not verify with its leaf's key.

Field error#

silk
pub error: SignatureFailure

The signature failure.

UntrustedClientCertificate#

silk
UntrustedClientCertificate

The client's chain did not validate, and ClientAuth rejects such chains. Server.clientCertificateStatus gives the full validation error.

Field reason#

silk
pub reason: ValidationReason

Why the chain did not validate.

Implementation Copy for ServerError#

silk
impl Copy for ServerError

Implementation Debug for ServerError#

silk
impl Debug for ServerError

Operation debug#

silk
effect fn debug(self: &Self, formatter: &mut Formatter) -> ()
    ! WriterError
    ? &mut Writer

Writes the name of the variant and its fields, such as PeerAlert { ... }.

Server#

silk
pub struct Server

A TLS 1.2 and TLS 1.3 server state machine that does no I/O.

When to use#

Make one server for each accepted connection with Server.make. Then move bytes between it and the transport until it reports HandshakeComplete, and then read and write application data.

Details#

Each operation returns a ServerProgress with a ServerDemand that tells you what to do next. Output works in two steps: write Server.pendingOutput to the transport, and then call Server.ackWritten with the number of bytes written. The server does not keep your buffers.

Gotchas#

A ServerError from a call after Server.make is permanent for the server. The server sends no alert when it fails. In TLS 1.2 it does not resume sessions, has no KeyUpdate, and refuses renegotiation. Dropping the server does not send close_notify. Call Server.closeWrite first. Secrets are not erased.

Implementation Server#

silk
impl Server

Associated function make#

silk
pub effect fn make<'a>(config: &ServerConfig<'a>, key: SigningKey) -> Result<Server, ServerError>
    ! OutOfMemoryError
    ? &mut Allocator

Returns a new server for config and the leaf's private key, waiting for the ClientHello.

The server copies the chain and the ALPN protocols. It decodes the leaf certificate and checks that its public key is the public key of key.

Errors#

  • EmptyCertificateChain, CertificateDecode, or KeyMismatch for a chain that is not valid.

  • LimitExceeded for limits, a chain, or ALPN protocols that are not valid.

  • OutOfMemoryError if the Allocator fails.

Method pendingOutput#

silk
pub fn pendingOutput<'a>(self: &'a Self) -> &'a [u8]

Returns the TLS output to send to the client. After you send some of it, call Server.ackWritten.

Method serverName#

silk
pub fn serverName<'a>(self: &'a Self) -> Option<&'a [u8]>

Returns the host name that the client sent in its SNI extension, after the server read the ClientHello. Before that, or without SNI, returns None.

Method selectedAlpn#

silk
pub fn selectedAlpn<'a>(self: &'a Self) -> Option<&'a [u8]>

Returns the ALPN protocol that the server selected, after the server read the ClientHello. Before that, or without a selection, returns None.

Method cipherSuite#

silk
pub fn cipherSuite(self: &Self) -> Option<CipherSuite>

Returns the negotiated cipher suite after the HandshakeComplete action. Before that, returns None.

Method version#

silk
pub fn version(self: &Self) -> Option<TlsVersion>

Returns the negotiated TLS version after the HandshakeComplete action. Before that, returns None.

Method group#

silk
pub fn group(self: &Self) -> Option<ServerGroup>

Returns the negotiated key exchange group after the HandshakeComplete action. Before that, returns None.

Method retried#

silk
pub fn retried(self: &Self) -> bool

Returns whether the server sent a HelloRetryRequest in this handshake.

Method resumed#

silk
pub fn resumed(self: &Self) -> bool

Returns whether the handshake resumed a session from a ticket, after the server read the ClientHello. A resumed handshake sends no certificates.

Method earlyData#

silk
pub fn earlyData(self: &Self) -> EarlyDataStatus

Returns what happened to the client's 0-RTT data, after the server read the ClientHello. It is NotOffered, Accepted, or Rejected. Plaintext that you read before HandshakeComplete is accepted early data.

Method clientCertificateStatus#

silk
pub fn clientCertificateStatus<'a>(self: &'a Self) -> &'a ClientCertificateStatus

Returns what the server knows about the client's certificate. After HandshakeComplete it is NotRequested, Absent, Trusted, or Untrusted.

Method clientCertificates#

silk
pub fn clientCertificates<'a>(self: &'a Self) -> &'a [Certificate]

Returns the client's certificates, leaf first, as the client sent them. It is empty until the client's Certificate message arrives, and when the client sent none.

Method closeNotified#

silk
pub fn closeNotified(self: &Self) -> bool

Returns whether the client sent close_notify. Plaintext that came before it can still be read.

Method feedInput#

silk
pub effect fn feedInput(self: &mut Self, input: &[u8]) -> Result<ServerProgress, ServerError>
    ! OutOfMemoryError
    ? &mut Allocator | &mut Random

Gives bytes from the client to the server. consumed in the result tells how many it accepted.

Details#

The server does not keep input. Give the bytes that it did not accept again in the next call. During the handshake, it accepts no bytes while output is pending. After the client sends close_notify, the server accepts and ignores all later bytes.

Method progress#

silk
pub effect fn progress(self: &mut Self) -> Result<ServerProgress, ServerError>
    ! OutOfMemoryError
    ? &mut Allocator | &mut Random

Processes buffered handshake messages without new input, and returns the next action.

Method ackWritten#

silk
pub fn ackWritten(self: &mut Self, count: usize) -> Result<ServerProgress, ServerError>

Tells the server that the transport sent the first count bytes of Server.pendingOutput.

Method readPlaintext#

silk
pub fn readPlaintext(self: &mut Self, output: &mut [u8]) -> Result<ServerProgress, ServerError>

Copies decrypted application data into output. written in the result tells how many bytes.

Gotchas#

An empty output returns the EmptyBuffer error. It never means the end of input.

Method writePlaintext#

silk
pub fn writePlaintext(self: &mut Self, input: &[u8]) -> Result<ServerProgress, ServerError>

Encrypts a prefix of input, at most 16384 bytes. consumed in the result tells how many bytes.

Details#

When TLS output is waiting, the server accepts no bytes. Send that output first. Do not give accepted bytes again, even if the transport sent only part of the record.

Method requestKeyUpdate#

silk
pub fn requestKeyUpdate(self: &mut Self) -> Result<ServerProgress, ServerError>

Asks for a new local traffic key before the next application write. More calls before that write do nothing.

Method closeWrite#

silk
pub fn closeWrite(self: &mut Self) -> Result<ServerProgress, ServerError>

Queues close_notify after the accepted output. More calls do nothing.

Method endInput#

silk
pub fn endInput(self: &mut Self) -> Result<ServerProgress, ServerError>

Tells the server that the transport has no more input. Pending output stays pending.

Category: TLS and certificates.

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.

View the source of this page