Uploaded image for project: 'Erlang/OTP'
  1. Erlang/OTP
  2. ERL-825

Unsupported curves returned in crypto:ec_curves() on RHEL/CentOS/Fedora OpenSSL with FIPS support



    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Won't Fix
    • Affects Version/s: 21.0, 20.3, 21.1, 21.2
    • Fix Version/s: OTP-23.0-rc3
    • Component/s: crypto
    • Labels:


      This is a follow-up to ERL-823.

      When building Erlang on RedHat/CentOS/Fedora-based systems with the default OpenSSL library, a number of elliptic curves are listed as supported, but result in a runtime error when referenced in Erlang code.

      This appears to impact crypto when using RHEL/CentOS/Fedora OpenSSL libraries, which are built with FIPS support (but not with it turned on, or with enabled in the Erlang build via --enable-fips). Here are some example systems that are impacted:

      • OpenSSL 1.0.1e-fips 11 Feb 2013 (CentOS release 6.9)
      • OpenSSL 1.0.2k-fips 26 Jan 2017 (Amazon Linux AMI release 2017.09)
      • OpenSSL 1.0.2k-fips 26 Jan 2017 (Amazon Linux AMI release 2018.03)

      I haven't done a thorough examination, but I suppose that this impacts the "system" OpenSSL for most if not all RHEL/CentOS/Fedora releases (and derivatives, like Amazon Linux) over the past 5 years.

      The following curves result in a runtime error:

      • brainpoolP160r1
      • brainpoolP160t1
      • brainpoolP192r1
      • brainpoolP192t1
      • brainpoolP224r1
      • brainpoolP224t1
      • prime192v1
      • prime192v2
      • prime192v3
      • prime239v1
      • prime239v2
      • prime239v3
      • secp112r1
      • secp112r2
      • secp128r1
      • secp128r2
      • secp160k1
      • secp160r1
      • secp160r2
      • secp192r1
      • secp192k1
      • secp224k1
      • secp224r1
      • wtls6
      • wtls7
      • wtls8
      • wtls9
      • wtls12

      On the other hand, these similar curves function as expected:

      • brainpoolP256r1
      • brainpoolP256t1
      • brainpoolP320r1
      • brainpoolP320t1
      • brainpoolP384r1
      • brainpoolP384t1
      • brainpoolP512r1
      • brainpoolP512t1
      • prime256v1
      • secp256k1
      • secp256r1
      • secp384r1
      • secp521r1

      This appears to be due to an intentional limitation of OpenSSL with the OPENSSL_FIPS set, even if it is not explicitly enabled. It may be limited to RHEL/CentOS/Fedora-based OpenSSLs, but I am not sure. I've noticed this commit in OTP: Check the result of EC_GROUP_new_curve_* calls:

      The FIPS-enabled OpenSSL on RHEL disallows the use of < 256 bit prime
      fields (like secp128r1 or secp160k1), and the EC_GROUP_new_cuve_GFp
      call would return a NULL pointer for such fields. Not checking for
      this failure could result in a segfault in the NIF code.

      The commit above observed the issue, but it looks like it just returns an error when these curves are used. It seems like it would be preferable to disable support for these non-functioning curves when this OPENSSL_FIPS header is defined.

      The following example code can be used to demonstrate this problem.

      VerifyCurve = fun(Curve) ->
          Msg = <<"hello world!">>,
              {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]),
             Err:Reason ->
                 {Err, Reason}

      When I run this on the outputs of the curves in crypto:ec_curves/0, I get this result:

      1> rp([{C, VerifyCurve(C)} || C <- crypto:ec_curves()]).


          Issue Links



              otp_team_ps Team PS
              nalundgaard Nicholas Lundgaard
              0 Vote for this issue
              6 Start watching this issue