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

Nicholas Lundgaard <>
Fri Jan 4 18:41:16 CET 2019


Thanks for your insights, all.

I've looked at Erlang/OTP 21 builds from our CentOS box that were built with no OPENSSL_NO_EC* set, and also just tried one built with OPENSSL_NO_EC2M set, as advised below. It looks like it's true that these options are ideal for my company's use, and in both cases we properly get an Erlang/OTP build that has a fine set of cipher suites that work with the underlying OpenSSL library on the OS.

It seems like there is still some potential problem with this setup, though: both the ssl and crypto modules claim to support EC curves that the underlying SSL library does not, in fact, support. A simple function that wraps a key-generate/sign/verify process in a try-catch can be used to verify this:

VerifyCurve = fun(Curve) ->
    Msg = <<"hello world!">>,
    try
        {PublicKey, PrivKeyOut} = crypto:generate_key(ecdh,Curve),
        Signature = crypto:sign(ecdsa, sha512, Msg, [PrivKeyOut, Curve]),
        true = crypto:verify(ecdsa, sha512, <<"hello world!">>, Signature, [PublicKey, Curve]),
        ok
    catch
       Err:Reason ->
           {Err, Reason}
    end
end.

When I run this on ssl:eccs/0 or crypto:ec_curves/0, I get this result:

2> [{C, VerifyCurve(C)} || C <- ssl:eccs()].
[{secp521r1,ok},
 {brainpoolP512r1,ok},
 {brainpoolP384r1,ok},
 {secp384r1,ok},
 {brainpoolP256r1,ok},
 {secp256k1,ok},
 {secp256r1,ok},
 {secp224k1,{error,badarg}},
 {secp224r1,{error,badarg}},
 {secp192k1,{error,badarg}},
 {secp192r1,{error,badarg}},
 {secp160k1,{error,badarg}},
 {secp160r1,{error,badarg}},
 {secp160r2,{error,badarg}}]

3> rp([{C, VerifyCurve(C)} || C <- crypto:ec_curves()]).
[{secp160k1,{error,badarg}},
 {secp160r1,{error,badarg}},
 {secp160r2,{error,badarg}},
 {secp192r1,{error,badarg}},
 {secp192k1,{error,badarg}},
 {secp224k1,{error,badarg}},
 {secp224r1,{error,badarg}},
 {secp256k1,ok},
 {secp256r1,ok},
 {secp384r1,ok},
 {secp521r1,ok},
 {prime192v1,{error,badarg}},
 {prime192v2,{error,badarg}},
 {prime192v3,{error,badarg}},
 {prime239v1,{error,badarg}},
 {prime239v2,{error,badarg}},
 {prime239v3,{error,badarg}},
 {prime256v1,ok},
 {wtls7,{error,badarg}},
 {wtls9,{error,badarg}},
 {wtls12,{error,badarg}},
 {brainpoolP160r1,{error,badarg}},
 {brainpoolP160t1,{error,badarg}},
 {brainpoolP192r1,{error,badarg}},
 {brainpoolP192t1,{error,badarg}},
 {brainpoolP224r1,{error,badarg}},
 {brainpoolP224t1,{error,badarg}},
 {brainpoolP256r1,ok},
 {brainpoolP256t1,ok},
 {brainpoolP320r1,ok},
 {brainpoolP320t1,ok},
 {brainpoolP384r1,ok},
 {brainpoolP384t1,ok},
 {brainpoolP512r1,ok},
 {brainpoolP512t1,ok},
 {secp112r1,{error,badarg}},
 {secp112r2,{error,badarg}},
 {secp128r1,{error,badarg}},
 {secp128r2,{error,badarg}},
 {wtls6,{error,badarg}},
 {wtls8,{error,badarg}}]

So.. this is what actually is troubling me about an OTP that is installed this way: these two modules definitely report named curves that cause runtime errors. The underlying OpenSSL library definitely reports which ones it supports, so I guess my question is why doesn't ssl/crypto leverage this?

I think in point of fact, this concern isn't significant. It appears that Erlang/OTP 21 (built on RHEL/CentOS) has an SSL that works out of the box for most SSL connections, certainly to the hosts we care about (AWS services and ELBs/gateways in front of our infrastructure) and I'm guessing that's because the first 7 curves from "ssl:eccs/0" are, in fact, supported by the underlying OpenSSL library (and the list is in preference order). If I understand correctly, it would only be a problem to negotiate a connection with a peer  who does not support any of the first 7 preferred curves. 

So, I understand that a workaround that I could implement in my HTTPS clients in Erlang is to cull the list of eccs, which can be passed explicitly when connecting (e.g., [{eccs, [secp521r1, brainpoolP512r1, brainpoolP384r1, secp384r1, brainpoolP256r1, secp256k1, secp256r1]}]). However, I feel that this begs the question, what is the reason for the ssl/crypto modules not reporting a lack of support for unsupported curves?

Thanks again! I will copy-paste this comment into the ERL-823 issue as well, for the record.

Regards,
—Nicholas Lundgaard

On Fri, Jan 4, 2019, at 6:07 AM, Per Hedeland wrote:
> On 2019-01-04 10:38, Andreas Schultz wrote:
> > Nicholas Lundgaard < <mailto:>> schrieb am Do., 3. Jan. 2019 um 21:18 Uhr:
> > 
> >     Hi,
> > 
> >     I wanted to call ERL-823 (https://bugs.erlang.org/browse/ERL-823) to this list's attention. My company operates Erlang microservices in AWS on a kerl-built OTP installation on Amazon Linux
> >     (RedHat/CentOS-based), and we've encountered a serious challenge to upgrading to OTP 21:
> > 
> > 
> > ECC Ciphers are supported since RHEL 7.6 (also newer CentOS versions), Amazon Linux 2018.03 also has support (`openssl ciphers -v` does contain ECDH ciphers).
> 
> Actually I think there is some confusion here - also older versions of
> RHEL/CentOS(/Fedora?) support ECC cipher suites (I checked CentOS 7.2
> just now) - it is only a specific *set of curves* they don't support
> (and probably newer versions don't either), due to concerns about
> potential patents.
> 
> And there was actually a time when you *had* to use the brutal
> OPENSSL_NO_EC=1 workaround/hack to get OTP crypto to work on these
> systems, since crypto.c couldn't handle this "partial" exclusion of
> curves - depending on how you built it (excluding static linking* of
> libcrypto), you would get a failure either at build or run time.
> 
> But that was long ago, crypto.c was fixed in this respect already for
> OTP 17, in https://github.com/erlang/otp/commit/8837c1be2ba, by -
> Andreas Schultz! Thanks for that!:-)
> 
> So, if you use OTP 17 or newer:
> 
> - If you build with the libcrypto shipped with RHEL/CentOS, it will
>    "just work", without the OPENSSL_NO_EC hack.
> 
> - If you for some reason build with a libcrypto that *includes* the
>    curves that are excluded on those systems, you can still do a build
>    that works there, *and* makes ECC suites in general available, by
>    using OPENSSL_NO_EC2M=1 *instead* of OPENSSL_NO_EC=1.
> 
> I guess the moral is that if you are given a recipe for some problem,
> make sure that you understand why it is needed, so you can stop using
> it when the actual problem is fixed...:-)
> 
> *) I Am Not A Lawyer, but I will still advise at least those shipping
> commercial products based on Erlang/OTP to look carefully into the
> general legal issues with statically linking libcrypto into those
> products. And after having done that, to think again about the wisdom
> of doing the static linking specifically to be able to include
> algorithms that may be patented.
> 
> --Per Hedeland
>


More information about the erlang-questions mailing list