[erlang-questions] ERL-823: SSL cipher_suites too limited when compiling with OPENSSL_NO_EC=1

Fred Hebert <>
Fri Jan 4 03:41:49 CET 2019


On 01/03, Ingela Andin wrote:
>I say it would be a lot easier to configure the erlang cipher suites the
>way you like and skip trying to tweak OpenSSL.  Please see ERL382.
>
>Regards Ingela Erlang/OTP team
>

Additionally, Heroku has an open source library to handle TLS servers 
with SNI for dispatch, which comes with some default configurations and 
ways to easily translate from a known SSL list of ciphers such as what 
you'd find at:

- https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html
- https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29

In all of these lists, the format chosen is something like 
ECDHE-ECDSA-AES128-GCM-SHA256 rather than the Erlang-specific maps like  
#{cipher => aes_128_cbc,key_exchange => ecdhe_rsa, mac => sha256,prf => 
sha256} or {ecdhe_ecdsa,aes_128_gcm,null,sha256} (in OTP 20.2 and 
earlier)

To facilitate with this, I've written and updated their lib (PR pending) 
to include procedures to make the conversion between both formats easy:
https://github.com/heroku/snit/pull/36/files#diff-1ea45e0c99dd72cbe37b5b3f4f561c70R38

It goes a bit like this:

    %% Declare the list of suites you want in the order you need them
    OpenSSLSuites = [
        "ECDHE-ECDSA-AES128-GCM-SHA256",
        "ECDHE-ECDSA-AES256-GCM-SHA384",
        "ECDHE-RSA-AES128-GCM-SHA256",
        ...
    ],
    
    %% Declare the supported TLS versions you want (you may want to drop 
    %% tlsv1 and possibly 'tlsv1.1' as well, depending on compatibility
    SupportedVersions = [tlsv1, 'tlsv1.1', 'tlsv1.2'],
    
    %% Then run the following (see the source file for equivalents in
    %% older versions of Erlang and OTP)
    Suites = lists:usort(lists:append(
        [ssl:cipher_suites(all, Vsn) || Vsn <- SupportedVersions]
    )),
    Table = [{Str, [S]}  || S <- Suites,
                            Raw <- [ssl_cipher_format:suite(S)],
                            Str <- [ssl_cipher_format:openssl_suite_name(Raw)],
                            not is_map(Str)],
    [lists:keyfind(Suite, 1, Table) || Suite <- OpenSSLSuites].

This gives a full table of all currently supported suites with both the 
OpenSSL and the Erlang format, such as:

    [{"ECDHE-ECDSA-AES128-GCM-SHA256",
      [#{cipher => aes_128_gcm,key_exchange => ecdhe_ecdsa,
         mac => aead,prf => sha256}]},
     {"ECDHE-ECDSA-AES256-GCM-SHA384",
      [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
         mac => aead,prf => sha384}]},
     {"ECDHE-RSA-AES128-GCM-SHA256",
      [#{cipher => aes_128_gcm,key_exchange => ecdhe_rsa,mac => aead,
         prf => sha256}]},
     ...
    ]

Which in my opinion, makes it a lot easier to manage configurations if 
you don't want to carefully groom them all -- just copy a list you trust 
from some source online and get it applied directly. Snit uses that list 
and re-validates it at start time, but it would be easy to retransform 
it by just using lists:flatten([Map || {_Name, Map} <- Result]) for the 
format the Erlang ssl lib uses natively.

This also has the benefit that if you have any infosec department, 
they'll love you for providing them a list and format they're familiar 
with rather than the unique internal erlang format.

Regards,
Fred.


More information about the erlang-questions mailing list