Repository: randombit/botan
Pull request #2020 (2019-07-05 08:43:40)

Remove BearSSL provider
Reverting #1094 

Comparing the situation with the OpenSSL provider:

* OpenSSL is (sometimes) faster
* OpenSSL or a compatible fork is installed everywhere

BearSSL

* Seems to be much slower
* Is not included in any distribution I know of
* As a result of not being distributed, the integration isn't tested in CI either

BearSSL has good qualities and makes sense for bootloader or small embedded systems. But in such environments it doesn't make sense to bring along Botan for the ride. And in environments where Botan fits, BearSSL doesn't bring anything to the table.

CC @bluerise


Patch:
diff --git a/configure.py b/configure.py
index a82d99895..7cc6afab1 100755
--- a/configure.py
+++ b/configure.py
@@ -545,7 +545,7 @@ def process_command_line(args): # pylint: disable=too-many-locals,too-many-state
                           help='minimize build')
 
     # Should be derived from info.txt but this runs too early
-    third_party = ['bearssl', 'boost', 'bzip2', 'lzma', 'openssl', 'commoncrypto', 'sqlite3', 'zlib', 'tpm']
+    third_party = ['boost', 'bzip2', 'lzma', 'openssl', 'commoncrypto', 'sqlite3', 'zlib', 'tpm']
 
     for mod in third_party:
         mods_group.add_option('--with-%s' % (mod),
diff --git a/doc/building.rst b/doc/building.rst
index c5e0d2c63..fd3eb338e 100644
--- a/doc/building.rst
+++ b/doc/building.rst
@@ -60,7 +60,7 @@ we might see lines like::
    INFO: Skipping (incompatible OS): darwin_secrandom getentropy win32_stats
    INFO: Skipping (incompatible compiler): aes_armv8 pmull sha1_armv8 sha2_32_armv8
    INFO: Skipping (no enabled compression schemes): compression
-   INFO: Skipping (requires external dependency): bearssl boost bzip2 lzma openssl sqlite3 tpm zlib
+   INFO: Skipping (requires external dependency): boost bzip2 lzma openssl sqlite3 tpm zlib
 
 The ones that are skipped because they are require an external
 dependency have to be explicitly asked for, because they rely on third
diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp
index ab29e6772..63218006c 100644
--- a/src/lib/hash/hash.cpp
+++ b/src/lib/hash/hash.cpp
@@ -93,10 +93,6 @@
   #include <botan/blake2b.h>
 #endif
 
-#if defined(BOTAN_HAS_BEARSSL)
-  #include <botan/internal/bearssl.h>
-#endif
-
 #if defined(BOTAN_HAS_OPENSSL)
   #include <botan/internal/openssl.h>
 #endif
@@ -133,17 +129,6 @@ std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
       }
 #endif
 
-#if defined(BOTAN_HAS_BEARSSL)
-   if(provider.empty() || provider == "bearssl")
-      {
-      if(auto hash = make_bearssl_hash(algo_spec))
-         return hash;
-
-      if(!provider.empty())
-         return nullptr;
-      }
-#endif
-
    if(provider.empty() == false && provider != "base")
       return nullptr; // unknown provider
 
@@ -368,7 +353,7 @@ HashFunction::create_or_throw(const std::string& algo,
 
 std::vector<std::string> HashFunction::providers(const std::string& algo_spec)
    {
-   return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl", "commoncrypto"});
+   return probe_providers_of<HashFunction>(algo_spec, {"base", "openssl", "commoncrypto"});
    }
 
 }
diff --git a/src/lib/prov/bearssl/bearssl.h b/src/lib/prov/bearssl/bearssl.h
deleted file mode 100644
index e6d77fcfa..000000000
--- a/src/lib/prov/bearssl/bearssl.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-* Utils for calling BearSSL
-* (C) 2015,2016 Jack Lloyd
-* (C) 2017 Patrick Wildt
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#ifndef BOTAN_INTERNAL_BEARSSL_H_
-#define BOTAN_INTERNAL_BEARSSL_H_
-
-#include <botan/pk_ops_fwd.h>
-#include <botan/secmem.h>
-#include <botan/exceptn.h>
-#include <memory>
-#include <string>
-
-namespace Botan {
-
-class HashFunction;
-
-class BearSSL_Error final : public Exception
-   {
-   public:
-      BearSSL_Error(const std::string& what) :
-         Exception(what + " failed") {}
-   };
-
-/* Hash */
-
-std::unique_ptr<HashFunction>
-make_bearssl_hash(const std::string& name);
-
-/* ECDSA */
-
-#if defined(BOTAN_HAS_ECDSA)
-
-class ECDSA_PublicKey;
-class ECDSA_PrivateKey;
-
-std::unique_ptr<PK_Ops::Verification>
-make_bearssl_ecdsa_ver_op(const ECDSA_PublicKey& key, const std::string& params);
-std::unique_ptr<PK_Ops::Signature>
-make_bearssl_ecdsa_sig_op(const ECDSA_PrivateKey& key, const std::string& params);
-
-#endif
-
-}
-
-#endif
diff --git a/src/lib/prov/bearssl/bearssl_ec.cpp b/src/lib/prov/bearssl/bearssl_ec.cpp
deleted file mode 100644
index 89f7773aa..000000000
--- a/src/lib/prov/bearssl/bearssl_ec.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-* ECDSA via BearSSL
-* (C) 2015,2016 Jack Lloyd
-* (C) 2017 Patrick Wildt
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#include <botan/exceptn.h>
-#include <botan/hash.h>
-#include <botan/scan_name.h>
-#include <botan/internal/bearssl.h>
-
-#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
-  #include <botan/der_enc.h>
-  #include <botan/pkcs8.h>
-  #include <botan/oids.h>
-  #include <botan/internal/pk_ops_impl.h>
-#endif
-
-#if defined(BOTAN_HAS_ECDSA)
-  #include <botan/ecdsa.h>
-#endif
-
-extern "C" {
-  #include <bearssl_hash.h>
-  #include <bearssl_ec.h>
-}
-
-namespace Botan {
-
-#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
-
-namespace {
-
-int BearSSL_EC_curve_for(const OID& oid)
-   {
-   if(oid.empty())
-      return -1;
-
-   const std::string name = OIDS::lookup(oid);
-
-   if(name == "secp256r1")
-      return BR_EC_secp256r1;
-   if(name == "secp384r1")
-      return BR_EC_secp384r1;
-   if(name == "secp521r1")
-      return BR_EC_secp521r1;
-
-   return -1;
-   }
-
-const br_hash_class *BearSSL_hash_class_for(const std::string& emsa)
-   {
-   if (emsa == "EMSA1(SHA-1)")
-      return &br_sha1_vtable;
-   if (emsa == "EMSA1(SHA-224)")
-      return &br_sha224_vtable;
-   if (emsa == "EMSA1(SHA-256)")
-      return &br_sha256_vtable;
-   if (emsa == "EMSA1(SHA-384)")
-      return &br_sha384_vtable;
-   if (emsa == "EMSA1(SHA-512)")
-      return &br_sha512_vtable;
-
-   return nullptr;
-   }
-}
-
-#endif
-
-#if defined(BOTAN_HAS_ECDSA)
-
-namespace {
-
-class BearSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification
-   {
-   public:
-      BearSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa) :
-         m_order_bits(ecdsa.domain().get_order_bits())
-         {
-         const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
-         if (curve < 0)
-            throw Lookup_Error("BearSSL ECDSA does not support this curve");
-
-         m_hash = BearSSL_hash_class_for(emsa);
-         if (m_hash == nullptr)
-            throw Lookup_Error("BearSSL ECDSA does not support EMSA " + emsa);
-
-         const SCAN_Name req(emsa);
-         m_hf = make_bearssl_hash(req.arg(0));
-         if (m_hf == nullptr)
-            throw Lookup_Error("BearSSL ECDSA does not support hash " + req.arg(0));
-
-         m_q_buf = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
-
-         m_key.qlen = m_q_buf.size();
-         m_key.q = m_q_buf.data();
-         m_key.curve = curve;
-         }
-
-      void update(const uint8_t msg[], size_t msg_len) override
-         {
-         m_hf->update(msg, msg_len);
-         }
-
-      bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
-         {
-         const size_t order_bytes = (m_order_bits + 7) / 8;
-         if (sig_len != 2 * order_bytes)
-            return false;
-         secure_vector<uint8_t> msg = m_hf->final();
-
-         br_ecdsa_vrfy engine = br_ecdsa_vrfy_raw_get_default();
-         if (!engine(&br_ec_prime_i31, msg.data(), msg.size(), &m_key, sig, sig_len))
-             return false;
-
-         return true;
-         }
-
-      size_t max_input_bits() const { return m_order_bits; }
-
-   private:
-      br_ec_public_key m_key;
-      std::unique_ptr<HashFunction> m_hf;
-      std::vector<uint8_t> m_q_buf;
-      const br_hash_class *m_hash;
-      size_t m_order_bits;
-   };
-
-class BearSSL_ECDSA_Signing_Operation final : public PK_Ops::Signature
-   {
-   public:
-      BearSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) :
-         m_order_bits(ecdsa.domain().get_order_bits()),
-         m_order_bytes(ecdsa.domain().get_order_bytes())
-         {
-         const int curve = BearSSL_EC_curve_for(ecdsa.domain().get_oid());
-         if(curve < 0)
-            throw Lookup_Error("BearSSL ECDSA does not support this curve");
-
-         m_hash = BearSSL_hash_class_for(emsa);
-         if (m_hash == nullptr)
-            throw Lookup_Error("BearSSL ECDSA does not support EMSA " + emsa);
-
-         const SCAN_Name req(emsa);
-         m_hf = make_bearssl_hash(req.arg(0));
-         if (m_hf == nullptr)
-            throw Lookup_Error("BearSSL ECDSA does not support hash " + req.arg(0));
-
-         m_x_buf = BigInt::encode_locked(ecdsa.private_value());
-
-         m_key.xlen = m_x_buf.size();
-         m_key.x = m_x_buf.data();
-         m_key.curve = curve;
-         }
-
-      void update(const uint8_t msg[], size_t msg_len) override
-         {
-         m_hf->update(msg, msg_len);
-         }
-
-      secure_vector<uint8_t> sign(RandomNumberGenerator&) override
-         {
-         const size_t order_bytes = (m_order_bits + 7) / 8;
-         secure_vector<uint8_t> sigval(2*order_bytes);
-
-         br_ecdsa_sign engine = br_ecdsa_sign_raw_get_default();
-         size_t sign_len = engine(&br_ec_prime_i31, m_hash, m_hf->final().data(), &m_key, sigval.data());
-         if (sign_len == 0)
-            throw BearSSL_Error("br_ecdsa_sign");
-
-         sigval.resize(sign_len);
-         return sigval;
-         }
-
-      size_t max_input_bits() const { return m_order_bits; }
-
-      size_t signature_length() const override { return 2*m_order_bytes; }
-
-   private:
-      br_ec_private_key m_key;
-      std::unique_ptr<HashFunction> m_hf;
-      secure_vector<uint8_t> m_x_buf;
-      const br_hash_class *m_hash;
-      size_t m_order_bits;
-      size_t m_order_bytes;
-   };
-
-}
-
-std::unique_ptr<PK_Ops::Verification>
-make_bearssl_ecdsa_ver_op(const ECDSA_PublicKey& key, const std::string& params)
-   {
-   return std::unique_ptr<PK_Ops::Verification>(new BearSSL_ECDSA_Verification_Operation(key, params));
-   }
-
-std::unique_ptr<PK_Ops::Signature>
-make_bearssl_ecdsa_sig_op(const ECDSA_PrivateKey& key, const std::string& params)
-   {
-   return std::unique_ptr<PK_Ops::Signature>(new BearSSL_ECDSA_Signing_Operation(key, params));
-   }
-
-#endif
-
-}
diff --git a/src/lib/prov/bearssl/bearssl_hash.cpp b/src/lib/prov/bearssl/bearssl_hash.cpp
deleted file mode 100644
index 2b837bcf5..000000000
--- a/src/lib/prov/bearssl/bearssl_hash.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-* BearSSL Hash Functions
-* (C) 1999-2007,2015 Jack Lloyd
-* (C) 2017 Patrick Wildt
-*
-* Botan is released under the Simplified BSD License (see license.txt)
-*/
-
-#include <botan/hash.h>
-#include <botan/internal/bearssl.h>
-#include <unordered_map>
-
-extern "C" {
-  #include <bearssl_hash.h>
-}
-
-namespace Botan {
-
-namespace {
-
-class BearSSL_HashFunction final : public HashFunction
-   {
-   public:
-      void clear() override
-         {
-         m_ctx.vtable->init(&m_ctx.vtable);
-         }
-
-      std::string provider() const override { return "bearssl"; }
-      std::string name() const override { return m_name; }
-
-      HashFunction* clone() const override
-         {
-         return new BearSSL_HashFunction(m_ctx.vtable, m_name);
-         }
-
-      std::unique_ptr<HashFunction> copy_state() const override
-         {
-         std::unique_ptr<BearSSL_HashFunction> copy(new BearSSL_HashFunction(m_ctx.vtable, m_name));
-         std::memcpy(&copy->m_ctx, &m_ctx, sizeof(m_ctx));
-         return std::move(copy);
-         }
-
-      size_t output_length() const override
-         {
-         return (m_ctx.vtable->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
-         }
-
-      size_t hash_block_size() const override
-         {
-         return 1 << ((m_ctx.vtable->desc >> BR_HASHDESC_LBLEN_OFF) & BR_HASHDESC_LBLEN_MASK);
-         }
-
-      BearSSL_HashFunction(const br_hash_class *hash, const std::string name)
-         {
-         m_name = name;
-         hash->init(&m_ctx.vtable);
-         }
-
-      ~BearSSL_HashFunction()
-         {
-         }
-
-   private:
-      void add_data(const uint8_t input[], size_t length) override
-         {
-         m_ctx.vtable->update(&m_ctx.vtable, input, length);
-         }
-
-      void final_result(uint8_t output[]) override
-         {
-         m_ctx.vtable->out(&m_ctx.vtable, output);
-         m_ctx.vtable->init(&m_ctx.vtable);
-         }
-
-      std::string m_name;
-      br_hash_compat_context m_ctx;
-   };
-
-}
-
-std::unique_ptr<HashFunction>
-make_bearssl_hash(const std::string& name)
-   {
-#define MAKE_BEARSSL_HASH(vtable) \
-   std::unique_ptr<HashFunction>(new BearSSL_HashFunction(vtable, name))
-
-#if defined(BOTAN_HAS_SHA2_32)
-   if(name == "SHA-224")
-      return MAKE_BEARSSL_HASH(&br_sha224_vtable);
-   if(name == "SHA-256")
-      return MAKE_BEARSSL_HASH(&br_sha256_vtable);
-#endif
-
-#if defined(BOTAN_HAS_SHA2_64)
-   if(name == "SHA-384")
-      return MAKE_BEARSSL_HASH(&br_sha384_vtable);
-   if(name == "SHA-512")
-      return MAKE_BEARSSL_HASH(&br_sha512_vtable);
-#endif
-
-#if defined(BOTAN_HAS_SHA1)
-   if(name == "SHA-160" || name == "SHA-1" || name == "SHA1")
-      return MAKE_BEARSSL_HASH(&br_sha1_vtable);
-#endif
-
-#if defined(BOTAN_HAS_MD5)
-   if(name == "MD5")
-      return MAKE_BEARSSL_HASH(&br_md5_vtable);
-#endif
-
-#if defined(BOTAN_HAS_PARALLEL_HASH)
-   if(name == "Parallel(MD5,SHA-160)")
-      return MAKE_BEARSSL_HASH(&br_md5sha1_vtable);
-#endif
-
-   return nullptr;
-   }
-
-}
diff --git a/src/lib/prov/bearssl/info.txt b/src/lib/prov/bearssl/info.txt
deleted file mode 100644
index 67bdc157d..000000000
--- a/src/lib/prov/bearssl/info.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-<defines>
-BEARSSL -> 20170628
-</defines>
-
-load_on vendor
-
-<header:internal>
-bearssl.h
-</header:internal>
-
-<libs>
-all!windows -> bearssl
-</libs>
-
-<requires>
-pubkey
-</requires>
diff --git a/src/lib/pubkey/ecdsa/ecdsa.cpp b/src/lib/pubkey/ecdsa/ecdsa.cpp
index fadf1dd10..ebe9268cc 100644
--- a/src/lib/pubkey/ecdsa/ecdsa.cpp
+++ b/src/lib/pubkey/ecdsa/ecdsa.cpp
@@ -19,10 +19,6 @@
   #include <botan/rfc6979.h>
 #endif
 
-#if defined(BOTAN_HAS_BEARSSL)
-  #include <botan/internal/bearssl.h>
-#endif
-
 #if defined(BOTAN_HAS_OPENSSL)
   #include <botan/internal/openssl.h>
 #endif
@@ -262,21 +258,6 @@ std::unique_ptr<PK_Ops::Verification>
 ECDSA_PublicKey::create_verification_op(const std::string& params,
                                         const std::string& provider) const
    {
-#if defined(BOTAN_HAS_BEARSSL)
-   if(provider == "bearssl" || provider.empty())
-      {
-      try
-         {
-         return make_bearssl_ecdsa_ver_op(*this, params);
-         }
-      catch(Lookup_Error& e)
-         {
-         if(provider == "bearssl")
-            throw;
-         }
-      }
-#endif
-
 #if defined(BOTAN_HAS_OPENSSL)
    if(provider == "openssl" || provider.empty())
       {
@@ -303,21 +284,6 @@ ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& rng,
                                       const std::string& params,
                                       const std::string& provider) const
    {
-#if defined(BOTAN_HAS_BEARSSL)
-   if(provider == "bearssl" || provider.empty())
-      {
-      try
-         {
-         return make_bearssl_ecdsa_sig_op(*this, params);
-         }
-      catch(Lookup_Error& e)
-         {
-         if(provider == "bearssl")
-            throw;
-         }
-      }
-#endif
-
 #if defined(BOTAN_HAS_OPENSSL)
    if(provider == "openssl" || provider.empty())
       {


Test patch:
diff --git a/src/scripts/test_all_configs.py b/src/scripts/test_all_configs.py
index e0950e08f..53bd313b6 100755
--- a/src/scripts/test_all_configs.py
+++ b/src/scripts/test_all_configs.py
@@ -24,7 +24,6 @@ def get_module_list(configure_py):
         raise Exception("Running configure.py --list-modules failed")
 
     modules = [s.decode('ascii') for s in stdout.split()]
-    modules.remove('bearssl') # can't test
     modules.remove('tpm') # can't test
     modules.remove('base') # can't remove
     return modules
diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp
index 3d2526a78..c3a44a57d 100644
--- a/src/tests/test_pubkey.cpp
+++ b/src/tests/test_pubkey.cpp
@@ -93,7 +93,7 @@ std::string PK_Test::choose_padding(const VarMap& vars,
 
 std::vector<std::string> PK_Test::possible_providers(const std::string& /*params*/)
    {
-   return Test::provider_filter({ "base", "commoncrypto", "bearssl", "openssl", "tpm" });
+   return Test::provider_filter({ "base", "commoncrypto", "openssl", "tpm" });
    }
 
 Test::Result