diff options
author | Jack Lloyd <[email protected]> | 2021-10-23 14:37:02 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2021-10-28 17:24:09 -0400 |
commit | b77e5a1b663a8cfa0cfa90fd052a23eb70e9e31d (patch) | |
tree | 0a3e0341143cb34ebef86836393fd0e8d8c350e8 /src/lib/prov/openssl/openssl_ec.cpp | |
parent | 81e33dd31169fab2354c1ca45d59dd43a841a6bc (diff) |
Remove the OpenSSL provider
Starting in OpenSSL 3.0, most of the functionality which we need to
implement the OpenSSL provider is deprecated. Rather than reimplement
the whole provider in order to allow it to continue to work in the
future, just remove it. Efforts would be better spent doing more
optimization work rather than chasing OpenSSL's API changes.
Diffstat (limited to 'src/lib/prov/openssl/openssl_ec.cpp')
-rw-r--r-- | src/lib/prov/openssl/openssl_ec.cpp | 378 |
1 files changed, 0 insertions, 378 deletions
diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp deleted file mode 100644 index 88004ebe0..000000000 --- a/src/lib/prov/openssl/openssl_ec.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* -* ECDSA and ECDH via OpenSSL -* (C) 2015,2016 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/internal/openssl.h> - -#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) - #include <botan/der_enc.h> - #include <botan/pkcs8.h> - #include <botan/internal/pk_ops_impl.h> -#endif - -#if defined(BOTAN_HAS_ECDSA) - #include <botan/ecdsa.h> -#endif - -#if defined(BOTAN_HAS_ECDH) - #include <botan/ecdh.h> -#endif - -#include <openssl/x509.h> -#include <openssl/objects.h> - -#if !defined(OPENSSL_NO_EC) - #include <openssl/ec.h> -#endif - -#if !defined(OPENSSL_NO_ECDSA) - #include <openssl/ecdsa.h> -#endif - -#if !defined(OPENSSL_NO_ECDH) - #include <openssl/ecdh.h> -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) - -namespace { - -secure_vector<uint8_t> PKCS8_for_openssl(const EC_PrivateKey& ec) - { - const PointGFp& pub_key = ec.public_point(); - const BigInt& priv_key = ec.private_value(); - - return DER_Encoder() - .start_sequence() - .encode(static_cast<size_t>(1)) - .encode(BigInt::encode_1363(priv_key, priv_key.bytes()), ASN1_Type::OctetString) - .start_explicit_context_specific(0) - .raw_bytes(ec.domain().DER_encode(EC_Group_Encoding::NamedCurve)) - .end_cons() - .start_explicit_context_specific(1) - .encode(pub_key.encode(PointGFp::UNCOMPRESSED), ASN1_Type::BitString) - .end_cons() - .end_cons() - .get_contents(); - } - -int OpenSSL_EC_curve_builtin(int nid) - { - // the NID macro is still defined even though the curve may not be - // supported, so we need to check the list of builtin curves at runtime - EC_builtin_curve builtin_curves[100]; - size_t num = 0; - - if (!(num = EC_get_builtin_curves(builtin_curves, sizeof(builtin_curves)))) - { - return -1; - } - - for(size_t i = 0; i < num; ++i) - { - if(builtin_curves[i].nid == nid) - { - return nid; - } - } - - return -1; - } - -int OpenSSL_EC_nid_for(const OID& oid) - { - if(oid.empty()) - return -1; - - const std::string name = oid.to_formatted_string(); - - if(name == "secp192r1") - return OpenSSL_EC_curve_builtin(NID_X9_62_prime192v1); - if(name == "secp224r1") - return OpenSSL_EC_curve_builtin(NID_secp224r1); - if(name == "secp256r1") - return OpenSSL_EC_curve_builtin(NID_X9_62_prime256v1); - if(name == "secp384r1") - return OpenSSL_EC_curve_builtin(NID_secp384r1); - if(name == "secp521r1") - return OpenSSL_EC_curve_builtin(NID_secp521r1); - - // OpenSSL 1.0.2 added brainpool curves -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL - if(name == "brainpool160r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP160r1); - if(name == "brainpool192r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP192r1); - if(name == "brainpool224r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP224r1); - if(name == "brainpool256r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP256r1); - if(name == "brainpool320r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP320r1); - if(name == "brainpool384r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP384r1); - if(name == "brainpool512r1") - return OpenSSL_EC_curve_builtin(NID_brainpoolP512r1); -#endif - - return -1; - } - -} - -#endif - -#if defined(BOTAN_HAS_ECDSA) && !defined(OPENSSL_NO_ECDSA) - -namespace { - -class OpenSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification_with_EMSA - { - public: - OpenSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa, int nid) : - PK_Ops::Verification_with_EMSA(emsa), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free) - { - std::unique_ptr<::EC_GROUP, std::function<void (::EC_GROUP*)>> grp(::EC_GROUP_new_by_curve_name(nid), - ::EC_GROUP_free); - - if(!grp) - throw OpenSSL_Error("EC_GROUP_new_by_curve_name", ERR_get_error()); - - if(!::EC_KEY_set_group(m_ossl_ec.get(), grp.get())) - throw OpenSSL_Error("EC_KEY_set_group", ERR_get_error()); - - const std::vector<uint8_t> enc = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED); - const uint8_t* enc_ptr = enc.data(); - EC_KEY* key_ptr = m_ossl_ec.get(); - if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size())) - throw OpenSSL_Error("o2i_ECPublicKey", ERR_get_error()); - - const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); - m_order_bits = ::EC_GROUP_get_degree(group); - } - - size_t max_input_bits() const override { return m_order_bits; } - - bool with_recovery() const override { return false; } - - bool verify(const uint8_t msg[], size_t msg_len, - const uint8_t sig_bytes[], size_t sig_len) override - { - const size_t order_bytes = (m_order_bits + 7) / 8; - if(sig_len != 2 * order_bytes) - return false; - - std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(nullptr, ECDSA_SIG_free); - sig.reset(::ECDSA_SIG_new()); - - BIGNUM* r = BN_bin2bn(sig_bytes , static_cast<int>(sig_len / 2), nullptr); - BIGNUM* s = BN_bin2bn(sig_bytes + sig_len / 2, static_cast<int>(sig_len / 2), nullptr); - if(r == nullptr || s == nullptr) - throw OpenSSL_Error("BN_bin2bn sig s", ERR_get_error()); - - ECDSA_SIG_set0(sig.get(), r, s); - - const int res = ECDSA_do_verify(msg, static_cast<int>(msg_len), sig.get(), m_ossl_ec.get()); - if(res < 0) - { - auto err = ERR_get_error(); - - bool hard_error = true; - -#if defined(EC_R_BAD_SIGNATURE) - if(ERR_GET_REASON(err) == EC_R_BAD_SIGNATURE) - hard_error = false; -#endif -#if defined(EC_R_POINT_AT_INFINITY) - if(ERR_GET_REASON(err) == EC_R_POINT_AT_INFINITY) - hard_error = false; -#endif -#if defined(ECDSA_R_BAD_SIGNATURE) - if(ERR_GET_REASON(err) == ECDSA_R_BAD_SIGNATURE) - hard_error = false; -#endif - - if(hard_error) - throw OpenSSL_Error("ECDSA_do_verify", err); - } - return (res == 1); - } - - private: - std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec; - size_t m_order_bits = 0; - }; - -class OpenSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature_with_EMSA - { - public: - OpenSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) : - PK_Ops::Signature_with_EMSA(emsa), - m_ossl_ec(nullptr, ::EC_KEY_free) - { - const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdsa); - const uint8_t* der_ptr = der.data(); - m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size())); - if(!m_ossl_ec) - throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error()); - - const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); - m_order_bits = ::EC_GROUP_get_degree(group); - m_order_bytes = (m_order_bits + 7) / 8; - } - - size_t signature_length() const override { return 2*m_order_bytes; } - - secure_vector<uint8_t> raw_sign(const uint8_t msg[], size_t msg_len, - RandomNumberGenerator&) override - { - std::unique_ptr<ECDSA_SIG, std::function<void (ECDSA_SIG*)>> sig(nullptr, ECDSA_SIG_free); - sig.reset(::ECDSA_do_sign(msg, static_cast<int>(msg_len), m_ossl_ec.get())); - - if(!sig) - throw OpenSSL_Error("ECDSA_do_sign", ERR_get_error()); - -#if OPENSSL_VERSION_NUMBER < 0x10100000L - const BIGNUM* r = sig->r; - const BIGNUM* s = sig->s; -#else - const BIGNUM* r; - const BIGNUM* s; - ECDSA_SIG_get0(sig.get(), &r, &s); -#endif - - const size_t r_bytes = BN_num_bytes(r); - const size_t s_bytes = BN_num_bytes(s); - secure_vector<uint8_t> sigval(2*m_order_bytes); - BN_bn2bin(r, &sigval[m_order_bytes - r_bytes]); - BN_bn2bin(s, &sigval[2*m_order_bytes - s_bytes]); - return sigval; - } - - size_t max_input_bits() const override { return m_order_bits; } - - private: - std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec; - size_t m_order_bits; - size_t m_order_bytes; - }; - -} - -std::unique_ptr<PK_Ops::Verification> -make_openssl_ecdsa_ver_op(const ECDSA_PublicKey& key, const std::string& params) - { - const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid()); - if(nid < 0) - { - throw Lookup_Error("OpenSSL ECDSA does not support this curve"); - } - - try - { - return std::make_unique<OpenSSL_ECDSA_Verification_Operation>(key, params, nid); - } - catch(OpenSSL_Error&) - { - throw Lookup_Error("OpenSSL ECDSA does not support this key"); - } - } - -std::unique_ptr<PK_Ops::Signature> -make_openssl_ecdsa_sig_op(const ECDSA_PrivateKey& key, const std::string& params) - { - const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid()); - if(nid < 0) - { - throw Lookup_Error("OpenSSL ECDSA does not support this curve"); - } - return std::make_unique<OpenSSL_ECDSA_Signing_Operation>(key, params); - } - -#endif - -#if defined(BOTAN_HAS_ECDH) && !defined(OPENSSL_NO_ECDH) - -namespace { - -class OpenSSL_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF - { - public: - - OpenSSL_ECDH_KA_Operation(const ECDH_PrivateKey& ecdh, const std::string& kdf) : - PK_Ops::Key_Agreement_with_KDF(kdf), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free) - { - m_value_size = ecdh.domain().get_p_bytes(); - const secure_vector<uint8_t> der = PKCS8_for_openssl(ecdh); - const uint8_t* der_ptr = der.data(); - m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size())); - if(!m_ossl_ec) - throw OpenSSL_Error("d2i_ECPrivateKey", ERR_get_error()); - } - - size_t agreed_value_size() const override { return m_value_size; } - - secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override - { - const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); - const size_t out_len = (::EC_GROUP_get_degree(group) + 7) / 8; - secure_vector<uint8_t> out(out_len); - - std::unique_ptr<EC_POINT, std::function<void (EC_POINT*)>> pub_key( - ::EC_POINT_new(group), ::EC_POINT_free); - - if(!pub_key) - throw OpenSSL_Error("EC_POINT_new", ERR_get_error()); - - const int os2ecp_rc = - ::EC_POINT_oct2point(group, pub_key.get(), w, w_len, nullptr); - - if(os2ecp_rc != 1) - throw OpenSSL_Error("EC_POINT_oct2point", ERR_get_error()); - - const int ecdh_rc = ::ECDH_compute_key(out.data(), - out.size(), - pub_key.get(), - m_ossl_ec.get(), - /*KDF*/nullptr); - - if(ecdh_rc <= 0) - throw OpenSSL_Error("ECDH_compute_key", ERR_get_error()); - - const size_t ecdh_sz = static_cast<size_t>(ecdh_rc); - - if(ecdh_sz > out.size()) - throw Internal_Error("OpenSSL ECDH returned more than requested"); - - out.resize(ecdh_sz); - return out; - } - - private: - std::unique_ptr<EC_KEY, std::function<void (EC_KEY*)>> m_ossl_ec; - size_t m_value_size; - }; - -} - -std::unique_ptr<PK_Ops::Key_Agreement> -make_openssl_ecdh_ka_op(const ECDH_PrivateKey& key, const std::string& params) - { - const int nid = OpenSSL_EC_nid_for(key.domain().get_curve_oid()); - if(nid < 0) - { - throw Lookup_Error("OpenSSL ECDH does not support this curve"); - } - - return std::make_unique<OpenSSL_ECDH_KA_Operation>(key, params); - } - -#endif - -} - |