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:
Sovite.TLS.Certificate- loads certificate chains and keys.Sovite.TLS.CertStore- certificates by name, with SNI and reload.Sovite.TLS.DANE- DANE TLSA verification for SMTP (RFC 7672).Sovite.TLS.ACME- obtains certificates from an ACME CA (RFC 8555).
Summary
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
@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.
@type min_version() :: :"tlsv1.2" | :"tlsv1.3"
Lowest TLS version to accept.
Functions
@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.
@spec client_options(keyword()) :: [:ssl.tls_client_option()]
Returns :ssl client options.
Options
:verify-:none(default) to encrypt without checking the certificate, or:peerto check it against:cacertsand:hostname.:hostname- the server's name, sent with SNI and checked withverify: :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 inserver_options/1.:ciphers- as inserver_options/1.
@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).
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)"
Formats an :ssl error reason as text.
@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.
@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, seeciphers/1. Defaults todefault_ciphers/1.
@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"]