setupCustomRSA(const char* certPath, const char* keyPath, EventBase* jobEvb) {
  auto certPEM = getFileAsBuf(certPath);
  auto keyPEM = getFileAsBuf(keyPath);

  ssl::BioUniquePtr certBio(
      BIO_new_mem_buf((void*)certPEM.data(), certPEM.size()));
  ssl::BioUniquePtr keyBio(
      BIO_new_mem_buf((void*)keyPEM.data(), keyPEM.size()));

  ssl::X509UniquePtr cert(
      PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
  ssl::EvpPkeyUniquePtr evpPkey(
      PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr));
  ssl::EvpPkeyUniquePtr publicEvpPkey(X509_get_pubkey(cert.get()));

  std::unique_ptr<RSAPointers, RSAPointersDeleter> ret(new RSAPointers());

  RSA* actualrsa = EVP_PKEY_get1_RSA(evpPkey.get());
  LOG(INFO) << "actualrsa ptr " << std::hex << (void*)actualrsa;
  RSA* dummyrsa = EVP_PKEY_get1_RSA(publicEvpPkey.get());
  if (dummyrsa == nullptr) {
    throw std::runtime_error("Couldn't get RSA cert public factors");
  }
  RSA_METHOD* meth = RSA_meth_dup(RSA_get_default_method());
  if (meth == nullptr || RSA_meth_set1_name(meth, "Async RSA method") == 0 ||
      RSA_meth_set_priv_enc(meth, customRsaPrivEnc) == 0 ||
      RSA_meth_set_flags(meth, RSA_METHOD_FLAG_NO_CHECK) == 0) {
    throw std::runtime_error("Cannot create async RSA_METHOD");
  }
  RSA_set_method(dummyrsa, meth);
  RSA_set_flags(dummyrsa, RSA_FLAG_EXT_PKEY);

  kRSAExIndex = RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  kRSAEvbExIndex = RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  kRSASocketExIndex =
      RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  CHECK_NE(kRSAExIndex, -1);
  CHECK_NE(kRSAEvbExIndex, -1);
  CHECK_NE(kRSASocketExIndex, -1);
  RSA_set_ex_data(dummyrsa, kRSAExIndex, actualrsa);
  RSA_set_ex_data(dummyrsa, kRSAEvbExIndex, jobEvb);

  ret->actualrsa = actualrsa;
  ret->dummyrsa = dummyrsa;
  ret->meth = meth;

  return ret;
}
setupCustomRSA(const char* certPath, const char* keyPath, EventBase* jobEvb) {
  auto certPEM = getFileAsBuf(certPath);
  auto keyPEM = getFileAsBuf(keyPath);

  ssl::BioUniquePtr certBio(
      BIO_new_mem_buf((void*)certPEM.data(), certPEM.size()));
  ssl::BioUniquePtr keyBio(
      BIO_new_mem_buf((void*)keyPEM.data(), keyPEM.size()));

  ssl::X509UniquePtr cert(
      PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
  ssl::EvpPkeyUniquePtr evpPkey(
      PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr));
  ssl::EvpPkeyUniquePtr publicEvpPkey(X509_get_pubkey(cert.get()));

  std::unique_ptr<RSAPointers, RSAPointersDeleter> ret(new RSAPointers());

  RSA* actualrsa = EVP_PKEY_get1_RSA(evpPkey.get());
  LOG(INFO) << "actualrsa ptr " << std::hex << (void*)actualrsa;
  RSA* dummyrsa = EVP_PKEY_get1_RSA(publicEvpPkey.get());
  if (dummyrsa == nullptr) {
    throw std::runtime_error("Couldn't get RSA cert public factors");
  }
  RSA_METHOD* meth = RSA_meth_dup(RSA_get_default_method());
  if (meth == nullptr || RSA_meth_set1_name(meth, "Async RSA method") == 0 ||
      RSA_meth_set_priv_enc(meth, customRsaPrivEnc) == 0 ||
      RSA_meth_set_flags(meth, RSA_METHOD_FLAG_NO_CHECK) == 0) {
    throw std::runtime_error("Cannot create async RSA_METHOD");
  }
  RSA_set_method(dummyrsa, meth);
  RSA_set_flags(dummyrsa, RSA_FLAG_EXT_PKEY);

  kRSAExIndex = RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  kRSAEvbExIndex = RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  kRSASocketExIndex =
      RSA_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
  CHECK_NE(kRSAExIndex, -1);
  CHECK_NE(kRSAEvbExIndex, -1);
  CHECK_NE(kRSASocketExIndex, -1);
  RSA_set_ex_data(dummyrsa, kRSAExIndex, actualrsa);
  RSA_set_ex_data(dummyrsa, kRSAEvbExIndex, jobEvb);

  ret->actualrsa = actualrsa;
  ret->dummyrsa = dummyrsa;
  ret->meth = meth;

  return ret;
}