To see relevant version information for ssl, call ssl:versions/0 .

To see all supported cipher suites, call ssl:cipher_suites(all) . The available cipher suites for a connection depend on your certificate. Specific cipher suites that you want your connection to use can also be specified. Default is to use the strongest available.

## Setting up Connections

This section shows a small example of how to set up client/server connections using the Erlang shell. The returned value of the sslsocket is abbreviated with [...] as it can be fairly large and is opaque.

### Minimal Example

The minimal setup is not the most secure setup of SSL/TLS/DTLS.

To set up client/server connections:

Step 1: Start the server side:

`1 server> ssl:start(). ok`

Step 2: Create an TLS listen socket: (To run DTLS add the option {protocol, dtls})

`2 server> {ok, ListenSocket} = ssl:listen(9999, [{certfile, "cert.pem"}, {keyfile, "key.pem"},{reuseaddr, true}]). {ok,{sslsocket, [...]}}`

Step 3: Do a transport accept on the TLS listen socket:

`3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket). {ok,{sslsocket, [...]}}`

Step 4: Start the client side:

`1 client> ssl:start(). ok`

To run DTLS add the option {protocol, dtls} to third argument.

`2 client> {ok, Socket} = ssl:connect("localhost", 9999, [], infinity). {ok,{sslsocket, [...]}}`

Step 5: Do the TLS handshake:

`4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket). ok`

Step 6: Send a message over TLS:

`5 server> ssl:send(Socket, "foo"). ok`

Step 7: Flush the shell message queue to see that the message was sent on the server side:

`3 client> flush(). Shell got {ssl,{sslsocket,[...]},"foo"} ok`

### Upgrade Example - TLS only

To upgrade a TCP/IP connection to an SSL connection, the client and server must agree to do so. The agreement can be accomplished by using a protocol, for example, the one used by HTTP specified in RFC 2817.

To upgrade to an SSL connection:

Step 1: Start the server side:

`1 server> ssl:start(). ok`

Step 2: Create a normal TCP listen socket:

`2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true}]). {ok, #Port<0.475>}`

Step 3: Accept client connection:

`3 server> {ok, Socket} = gen_tcp:accept(ListenSocket). {ok, #Port<0.476>}`

Step 4: Start the client side:

`1 client> ssl:start(). ok` `2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999, [], infinity).`

Step 5: Ensure active is set to false before trying to upgrade a connection to an SSL connection, otherwise SSL handshake messages can be delivered to the wrong process:

`4 server> inet:setopts(Socket, [{active, false}]). ok`

Step 6: Do the TLS handshake:

`5 server> {ok, TLSSocket} = ssl:handshake(Socket, [{cacertfile, "cacerts.pem"}, {certfile, "cert.pem"}, {keyfile, "key.pem"}]). {ok,{sslsocket,[...]}}`

Step 7: Upgrade to an TLS connection. The client and server must agree upon the upgrade. The server must call ssl:handshake/2 before the client calls ssl:connect/3.

`3 client>{ok, TLSSocket} = ssl:connect(Socket, [{cacertfile, "cacerts.pem"}, {certfile, "cert.pem"}, {keyfile, "key.pem"}], infinity). {ok,{sslsocket,[...]}}`

Step 8: Send a message over TLS:

`4 client> ssl:send(TLSSocket, "foo"). ok`

Step 9: Set active true on the TLS socket:

`4 server> ssl:setopts(TLSSocket, [{active, true}]). ok`

Step 10: Flush the shell message queue to see that the message was sent on the client side:

`5 server> flush(). Shell got {ssl,{sslsocket,[...]},"foo"} ok`

## Customizing cipher suits

Fetch default cipher suite list for an TLS/DTLS version. Change default to all to get all possible cipher suites.

`1> Default = ssl:cipher_suites(default, 'tlsv1.2'). [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa, mac => aead,prf => sha384}, ....]`

In OTP 20 it is desirable to remove all cipher suites that uses rsa kexchange (removed from default in 21)

`2> NoRSA = ssl:filter_cipher_suites(Default, [{key_exchange, fun(rsa) -> false; (_) -> true end}]). [...]`

Pick just a few suites

`3> Suites = ssl:filter_cipher_suites(Default, [{key_exchange, fun(ecdh_ecdsa) -> true; (_) -> false end}, {cipher, fun(aes_128_cbc) ->true; (_) ->false end}]). [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa, mac => sha256,prf => sha256}, #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha, prf => default_prf}]`

Make some particular suites the most preferred, or least preferred by changing prepend to append.

`4>ssl:prepend_cipher_suites(Suites, Default). [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa, mac => sha256,prf => sha256}, #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha, prf => default_prf}, #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa, mac => sha384,prf => sha384}, ...]`

## Using an Engine Stored Key

Erlang ssl application is able to use private keys provided by OpenSSL engines using the following mechanism:

`1> ssl:start(). ok`

Load a crypto engine, should be done once per engine used. For example dynamically load the engine called MyEngine:

`2> {ok, EngineRef} = crypto:engine_load(<<"dynamic">>, [{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],[]). {ok,#Ref<0.2399045421.3028942852.173962>}`

Create a map with the engine information and the algorithm used by the engine:

`3> PrivKey = #{algorithm => rsa, engine => EngineRef, key_id => "id of the private key in Engine"}.`

Use the map in the ssl key option:

`4> {ok, SSLSocket} = ssl:connect("localhost", 9999, [{cacertfile, "cacerts.pem"}, {certfile, "cert.pem"}, {key, PrivKey}], infinity).`

See also crypto documentation