Opened 5 years ago

Last modified 4 years ago

#13128 new Bugs

boost asio does not initialize libressl library

Reported by: ioan pomian <ipomian@…> Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.64.0 Severity: Problem
Keywords: asio libressl Cc:

Description

When using the libressl library with boost asio, there is some library initialization code that depends on OPENSSL_VERSION_NUMBER that should be executed but it is not because libressl identifies itself with OPENSSL_VERSION_NUMBER 0x20000000L and the code in question is inside an #if (OPENSSL_VERSION_NUMBER < 0x10100000L)or an #if (OPENSSL_VERSION_NUMBER < 0x10000000L)

The code I'm referring to is in boost/asio/ssl/detail/impl/openssl_init.ipp as follows:

  • in openssl_init_base::do_init method there is the following code:
    #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
        ::SSL_library_init();
        ::SSL_load_error_strings();        
        ::OpenSSL_add_all_algorithms();
    
        mutexes_.resize(::CRYPTO_num_locks());
        for (size_t i = 0; i < mutexes_.size(); ++i)
          mutexes_[i].reset(new boost::asio::detail::mutex);
        ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
    #endif // (OPENSSL_VERSION_NUMBER < 0x10100000L) 
    #if (OPENSSL_VERSION_NUMBER < 0x10000000L)
        ::CRYPTO_set_id_callback(&do_init::openssl_id_func);
    #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
    
  • similarly, in ~do_init() the following sequence should also execute for libressl:
    #if (OPENSSL_VERSION_NUMBER < 0x10000000L)
        ::CRYPTO_set_id_callback(0);
    #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
    #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
        ::CRYPTO_set_locking_callback(0);
        ::ERR_free_strings();
        ::EVP_cleanup();
        ::CRYPTO_cleanup_all_ex_data();
    #endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
    
  • also in ~do_init() the ERR_remove_thread_state and ENGINE_cleanup functions should be called
    #elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
        ::ERR_remove_thread_state(NULL);
    #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
    
    #if !defined(OPENSSL_NO_ENGINE) \
      && (OPENSSL_VERSION_NUMBER < 0x10100000L)
        ::ENGINE_cleanup();
    #endif // !defined(OPENSSL_NO_ENGINE)
           // && (OPENSSL_VERSION_NUMBER < 0x10100000L)
    
  • the following openssl_id_func and openssl_locking_func should also be available for libressl, along with the vector of mutexes:
    #if (OPENSSL_VERSION_NUMBER < 0x10000000L)
      static unsigned long openssl_id_func()
      {
    #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
        return ::GetCurrentThreadId();
    #else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
        void* id = &errno;
        BOOST_ASIO_ASSERT(sizeof(unsigned long) >= sizeof(void*));
        return reinterpret_cast<unsigned long>(id);
    #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
      }
    #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
    
    #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
      static void openssl_locking_func(int mode, int n, 
        const char* /*file*/, int /*line*/)
      {
        if (mode & CRYPTO_LOCK)
          instance()->mutexes_[n]->lock();
        else
          instance()->mutexes_[n]->unlock();
      }
    
      // Mutexes to be used in locking callbacks.
      std::vector<boost::asio::detail::shared_ptr<
            boost::asio::detail::mutex> > mutexes_;
    #endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
    

Change History (2)

comment:1 by anonymous, 4 years ago

You should not attempt to initialize OpenSSL from boost code at all -- doing so conflicts with other initializations made by user code (or other libraries). These initialization (and un-initialization) routines aren't thread-safe. You also can't just stomp in and replace locks provided by user with those of your choosing.

Note: See TracTickets for help on using tickets.