Sovite.TLS (sovite v0.2.0)

Copy Markdown View Source

TLS settings for mail servers and clients, following BCP 195 (RFC 9325).

Only TLS 1.2 and 1.3 are enabled (RFC 8996). With TLS 1.2, only forward-secret AEAD cipher suites are allowed: ECDHE key exchange with AES-GCM or ChaCha20-Poly1305. TLS 1.3 suites are all AEAD. The server picks the cipher, and renegotiation started by the client is refused.

These functions return option lists for :ssl. Certificates come from a Sovite.TLS.CertStore, or are given directly.

Other parts of the TLS component:

Summary

Types

What a handshake negotiated, for logs and Received: headers.

Lowest TLS version to accept.

Functions

Converts cipher suite names to :ssl suites. Accepts OpenSSL names ("ECDHE-RSA-AES128-GCM-SHA256") and IANA names ("TLS_AES_128_GCM_SHA256"). Returns {:error, {:unknown_cipher, name}} for a name this system does not support, and {:error, {:weak_cipher, name}} for one without forward secrecy or an AEAD cipher.

Returns :ssl client options.

Returns the default cipher suites for min_version, in order of preference, as OpenSSL names (TLS 1.2) and IANA names (TLS 1.3).

Formats info the way Received: headers and logs show it.

Formats an :ssl error reason as text.

Returns what the handshake on socket negotiated.

Returns :ssl server options.

Returns the TLS versions from min_version up, newest first.

Types

info()

@type info() :: %{
  protocol: String.t(),
  cipher: String.t(),
  bits: pos_integer() | nil,
  sni: String.t() | nil
}

What a handshake negotiated, for logs and Received: headers.

min_version()

@type min_version() :: :"tlsv1.2" | :"tlsv1.3"

Lowest TLS version to accept.

Functions

ciphers(names)

@spec ciphers([String.t()]) :: {:ok, [:ssl.erl_cipher_suite()]} | {:error, term()}

Converts cipher suite names to :ssl suites. Accepts OpenSSL names ("ECDHE-RSA-AES128-GCM-SHA256") and IANA names ("TLS_AES_128_GCM_SHA256"). Returns {:error, {:unknown_cipher, name}} for a name this system does not support, and {:error, {:weak_cipher, name}} for one without forward secrecy or an AEAD cipher.

client_options(opts)

@spec client_options(keyword()) :: [:ssl.tls_client_option()]

Returns :ssl client options.

Options

  • :verify - :none (default) to encrypt without checking the certificate, or :peer to check it against :cacerts and :hostname.
  • :hostname - the server's name, sent with SNI and checked with verify: :peer. Leave it out for address literals.
  • :cacerts - trusted CA certificates (DER). Defaults to the system's (:public_key.cacerts_get/0).
  • :min_version - as in server_options/1.
  • :ciphers - as in server_options/1.

default_ciphers(atom)

@spec default_ciphers(min_version()) :: [String.t()]

Returns the default cipher suites for min_version, in order of preference, as OpenSSL names (TLS 1.2) and IANA names (TLS 1.3).

describe(info)

@spec describe(info()) :: String.t()

Formats info the way Received: headers and logs show it.

iex> Sovite.TLS.describe(%{protocol: "TLSv1.3", cipher: "TLS_AES_256_GCM_SHA384", bits: 256, sni: nil})
"TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)"

format_error(reason)

@spec format_error(term()) :: String.t()

Formats an :ssl error reason as text.

info(socket)

@spec info(:ssl.sslsocket()) :: {:ok, info()} | {:error, term()}

Returns what the handshake on socket negotiated.

protocol is "TLSv1.3" or "TLSv1.2", and cipher the IANA suite name. sni is the name the client asked for, on servers.

server_options(opts)

@spec server_options(keyword()) :: [:ssl.tls_server_option()]

Returns :ssl server options.

Options

  • :certs_keys - the default certificates, as for :ssl: a list of %{cert: [der], key: {type, der}}. Required.
  • :sni_fun - picks certificates by server name, see :ssl.
  • :min_version - :"tlsv1.2" (default) or :"tlsv1.3".
  • :ciphers - cipher suite names, see ciphers/1. Defaults to default_ciphers/1.

versions(atom)

@spec versions(min_version()) :: [:"tlsv1.3" | :"tlsv1.2", ...]

Returns the TLS versions from min_version up, newest first.

iex> Sovite.TLS.versions(:"tlsv1.2")
[:"tlsv1.3", :"tlsv1.2"]