/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "DHImpl.hpp"

#include <openssl-compat.h>
#include <openssl/aes.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/rsa.h>
#include <openssl/stack.h>
#include <openssl/x509.h>

#include <cctype>
#include <cstring>
#include <memory>

/*
static DH * m_dh = nullptr;
static string m_skAlgo;
static int    m_keySize = 0;
static BIGNUM * m_pubKeyOther = nullptr;
static unsigned char m_key[128] = {0};
static std::vector<X509*> m_serverCerts;
*/

static const char *dhP =
    "13528702063991073999718992897071702177131142188276542919088770094024269"
    "73079899070080419278066109785292538223079165925365098181867673946"
    "34756714063947534092593553024224277712367371302394452615862654308"
    "11180902979719649450105660478776364198726078338308557022096810447"
    "3500348898008043285865193451061481841186553";

static const char *dhG =
    "13058345680719715096166513407513969537624553636623932169016704425008150"
    "56576152779768716554354314319087014857769741104157332735258102835"
    "93126577393912282416840649805564834470583437473176415335737232689"
    "81480201869671811010996732593655666464627559582258861254878896534"
    "1273697569202082715873518528062345259949959";

static const int dhL = 1023;

static int DH_PUBKEY_set(DH_PUBKEY **x, EVP_PKEY *pkey);
static EVP_PKEY *DH_PUBKEY_get(DH_PUBKEY *key);
/*
static const EVP_CIPHER* getCipherFunc();
static int setSkAlgo(const char * skalgo);
*/

ASN1_SEQUENCE(
    DH_PUBKEY) = {ASN1_SIMPLE(DH_PUBKEY, algor, X509_ALGOR),
                  ASN1_SIMPLE(DH_PUBKEY, public_key,
                              ASN1_BIT_STRING)} ASN1_SEQUENCE_END(DH_PUBKEY)

    // This gives us the i2d/d2i x.509 (ASN1 DER) encode/decode functions
    IMPLEMENT_ASN1_FUNCTIONS(DH_PUBKEY)

    // Returns Error code
    int gf_initDhKeys(void **dhCtx, const char *dhAlgo, const char *ksPath) {
  int errorCode = DH_ERR_NO_ERROR;  // No error;

  auto dhimpl = new DHImpl();
  *dhCtx = dhimpl;

  // ksPath can be null
  if (dhimpl->m_dh || !dhAlgo || strlen(dhAlgo) == 0) {
    return errorCode;
  }

  // set the symmetric cipher algorithm name
  errorCode = dhimpl->setSkAlgo(dhAlgo);
  if (errorCode != DH_ERR_NO_ERROR) {
    return errorCode;
  }

  // do add-all here or outside in DS::connect?
  if (!DHImpl::m_init) {
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
    DHImpl::m_init = true;
  }

  dhimpl->m_dh = DH_new();

  BIGNUM *pbn = nullptr;
  BIGNUM *gbn = nullptr;
  DH_get0_pqg(dhimpl->m_dh, const_cast<const BIGNUM **>(&pbn), nullptr,
              const_cast<const BIGNUM **>(&gbn));
  BN_dec2bn(&pbn, dhP);

  LOGDH(" DHInit: P ptr is %p", pbn);
  LOGDH(" DHInit: G ptr is %p", gbn);
  LOGDH(" DHInit: length is %d", DH_get_length(dhimpl->m_dh));

  BN_dec2bn(&gbn, dhG);

  DH_set_length(dhimpl->m_dh, dhL);

  DH_generate_key(dhimpl->m_dh);

  const BIGNUM *pub_key, *priv_key;
  DH_get0_key(dhimpl->m_dh, &pub_key, &priv_key);
  BN_num_bits(priv_key);

  BN_num_bits(pub_key);

  int codes = 0;
  DH_check(dhimpl->m_dh, &codes);
  LOGDH(" DHInit: DH_check codes is 0x%04X", codes);
  LOGDH(" DHInit: DH_size is %d", DH_size(dhimpl->m_dh));

  // load the server's RSA public key for server authentication
  // note that OpenSSL 0.9.8g has a bug where it can read only the first one in
  // the keystore

  LOGDH(" Loading keystore...");

  if (ksPath == nullptr || strlen(ksPath) == 0) {
    LOGDH("Property \"security-client-kspath\" 's value is nullptr.");
    return errorCode;
  }
  FILE *keyStoreFP = nullptr;
  keyStoreFP = fopen(ksPath, "r");

  LOGDH(" kspath is [%s]", ksPath);
  LOGDH(" keystore FILE ptr is %p", keyStoreFP);

  // Read from pem file and put into.
  X509 *cert = nullptr;
  do {
    cert = PEM_read_X509(keyStoreFP, nullptr, nullptr, nullptr);

    if (cert != nullptr) {
      dhimpl->m_serverCerts.push_back(cert);
    }
  } while (cert != nullptr);

  LOGDH(" Total certificats imported # %zd", dhimpl->m_serverCerts.size());

  fclose(keyStoreFP);

  return errorCode;
}

void gf_clearDhKeys(void *dhCtx) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  if (dhimpl->m_dh != nullptr) {
    DH_free(dhimpl->m_dh);
    dhimpl->m_dh = nullptr;
  }

  std::vector<X509 *>::const_iterator iter;
  for (iter = dhimpl->m_serverCerts.begin();
       iter != dhimpl->m_serverCerts.end(); ++iter) {
    X509_free(*iter);
  }

  dhimpl->m_serverCerts.clear();

  if (dhimpl->m_pubKeyOther != nullptr) {
    BN_free(dhimpl->m_pubKeyOther);
    dhimpl->m_pubKeyOther = nullptr;
  }

  memset(dhimpl->m_key, 0, 128);

  // EVP_cleanup();
}

unsigned char *gf_getPublicKey(void *dhCtx, int *pLen) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  const BIGNUM *pub_key, *priv_key;
  DH_get0_key(dhimpl->m_dh, &pub_key, &priv_key);

  if (pub_key == nullptr || pLen == nullptr) {
    return nullptr;
  }

  int numBytes = BN_num_bytes(pub_key);

  if (numBytes <= 0) {
    return nullptr;
  }

  EVP_PKEY *evppubkey = EVP_PKEY_new();
  LOGDH(" before assign DH ptr is %p\n", dhimpl->m_dh);
  EVP_PKEY_assign_DH(evppubkey, dhimpl->m_dh);
  LOGDH(" after assign DH ptr is %p\n", dhimpl->m_dh);
  DH_PUBKEY *dhpubkey = nullptr;
  DH_PUBKEY_set(&dhpubkey, evppubkey);
  int len = i2d_DH_PUBKEY(dhpubkey, nullptr);
  unsigned char *pubkey = new unsigned char[len];
  unsigned char *temp = pubkey;
  //
  //  Note, this temp pointer is needed because OpenSSL increments the pointer
  //  passed in
  // so that following encoding can be done at the current output location, this
  // will cause a
  // problem if we try to free the pointer which has been moved by OpenSSL.
  //
  i2d_DH_PUBKEY(dhpubkey, &temp);

  //  TODO: uncomment this - causing problem in computeSecret?
  // DH_PUBKEY_free(dhpubkey);
  // EVP_PKEY_free(evppubkey);

  LOGDH(" after evp free DH ptr is %p\n", dhimpl->m_dh);
  *pLen = len;
  return pubkey;
}

void gf_setPublicKeyOther(void *dhCtx, const unsigned char *pubkey,
                          int length) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  if (dhimpl->m_pubKeyOther != nullptr) {
    BN_free(dhimpl->m_pubKeyOther);
    dhimpl->m_pubKeyOther = nullptr;
  }

  const unsigned char *temp = pubkey;
  DH_PUBKEY *dhpubkey = d2i_DH_PUBKEY(nullptr, &temp, length);
  LOGDH(" setPubKeyOther: after d2i_dhpubkey ptr is %p\n", dhpubkey);
  EVP_PKEY *evppkey = DH_PUBKEY_get(dhpubkey);
  LOGDH(" setPubKeyOther: after dhpubkey get evp ptr is %p\n", evppkey);
  LOGDH(" setPubKeyOther: before BNdup ptr is %p\n", dhimpl->m_pubKeyOther);

  const BIGNUM *pub_key, *priv_key;
  DH *dh = EVP_PKEY_get1_DH(evppkey);
  DH_get0_key(dh, &pub_key, &priv_key);
  dhimpl->m_pubKeyOther = BN_dup(pub_key);
  LOGDH(" setPubKeyOther: after BNdup ptr is %p\n", dhimpl->m_pubKeyOther);
  EVP_PKEY_free(evppkey);
  DH_PUBKEY_free(dhpubkey);

  int codes = 0;
  DH_check_pub_key(dhimpl->m_dh, dhimpl->m_pubKeyOther, &codes);
  LOGDH(" DHInit: DH check_pub_key codes is 0x%04X\n", codes);
}

void gf_computeSharedSecret(void *dhCtx) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  LOGDH("COMPUTE: DH ptr %p, pubkeyOther ptr %p", dhimpl->m_dh,
        dhimpl->m_pubKeyOther);

  LOGDH("DHcomputeKey DHSize is %d", DH_size(dhimpl->m_dh));
  DH_compute_key(dhimpl->m_key, dhimpl->m_pubKeyOther, dhimpl->m_dh);
  LOGDH("DHcomputeKey : Compute err(%d): %s", ERR_get_error(),
        ERR_error_string(ERR_get_error(), nullptr));
}

int DHImpl::setSkAlgo(const char *skalgo) {
  int errCode = DH_ERR_NO_ERROR;

  std::string inAlgo(skalgo);
  size_t colIdx = inAlgo.find(':');
  std::string algoStr =
      (colIdx == std::string::npos) ? inAlgo : inAlgo.substr(0, colIdx);
  int keySize = 0;

  // Convert input algo to lower case to support case insensitivity
  for (unsigned int i = 0; i < algoStr.size(); i++) {
    algoStr[i] = tolower(algoStr[i]);
  }

  if (algoStr == "aes") {
    keySize = (colIdx == std::string::npos)
                  ? 128
                  : atoi(inAlgo.substr(colIdx + 1).c_str());
    if (keySize == 128 || keySize == 192 || keySize == 256) {
      m_skAlgo = "AES";
      m_keySize = keySize;
    } else {
      return DH_ERR_ILLEGAL_KEYSIZE;
    }
  } else if (algoStr == "blowfish") {
    keySize = (colIdx == std::string::npos)
                  ? 128
                  : atoi(inAlgo.substr(colIdx + 1).c_str());
    if (keySize >= 128 && keySize <= 448) {
      m_skAlgo = "Blowfish";
      m_keySize = keySize;
    } else {
      return DH_ERR_ILLEGAL_KEYSIZE;
    }
  } else if (algoStr == "desede") {  // No keysize should be given
    if (colIdx == std::string::npos) {
      m_skAlgo = "DESede";
      m_keySize = 192;
    } else {
      return DH_ERR_ILLEGAL_KEYSIZE;
    }
  } else {
    return DH_ERR_UNSUPPORTED_ALGO;
  }

  LOGDH(" DH: Got SK algo as %s", m_skAlgo.c_str());
  LOGDH(" DH: Got keySize as %d", m_keySize);

  return errCode;
}

const EVP_CIPHER *DHImpl::getCipherFunc() {
  if (m_skAlgo == "AES") {
    if (m_keySize == 192) {
      return EVP_aes_192_cbc();
    } else if (m_keySize == 256) {
      return EVP_aes_256_cbc();
    } else {  // Default
      return EVP_aes_128_cbc();
    }
  } else if (m_skAlgo == "Blowfish") {
    return EVP_bf_cbc();
  } else if (m_skAlgo == "DESede") {
    return EVP_des_ede3_cbc();
  } else {
    LOGDH("ERROR: Unsupported DH Algorithm");
    return nullptr;
  }
}

unsigned char *gf_encryptDH(void *dhCtx, const unsigned char *cleartext,
                            int len, int *retLen) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  // Validation
  if (cleartext == nullptr || len < 1 || retLen == nullptr) {
    return nullptr;
  }

  LOGDH(" DH: gf_encryptDH using sk algo: %s, Keysize: %d",
        dhimpl->m_skAlgo.c_str(), dhimpl->m_keySize);

  auto ciphertext = std::unique_ptr<unsigned char[]>(
      new unsigned char[len + 50]);  // give enough room for padding
  int outlen, tmplen;
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

  const EVP_CIPHER *cipherFunc = dhimpl->getCipherFunc();

  // init openssl cipher context
  if (dhimpl->m_skAlgo == "AES") {
    int keySize = dhimpl->m_keySize > 128 ? dhimpl->m_keySize / 8 : 16;
    EVP_EncryptInit_ex(ctx, cipherFunc, nullptr, dhimpl->m_key,
                       dhimpl->m_key + keySize);
  } else if (dhimpl->m_skAlgo == "Blowfish") {
    int keySize = dhimpl->m_keySize > 128 ? dhimpl->m_keySize / 8 : 16;
    EVP_EncryptInit_ex(ctx, cipherFunc, nullptr, nullptr,
                       dhimpl->m_key + keySize);
    EVP_CIPHER_CTX_set_key_length(ctx, keySize);
    LOGDH("DHencrypt: BF keysize is %d", keySize);
    EVP_EncryptInit_ex(ctx, nullptr, nullptr, dhimpl->m_key, nullptr);
  } else if (dhimpl->m_skAlgo == "DESede") {
    EVP_EncryptInit_ex(ctx, cipherFunc, nullptr, dhimpl->m_key,
                       dhimpl->m_key + 24);
  }

  if (!EVP_EncryptUpdate(ctx, ciphertext.get(), &outlen, cleartext, len)) {
    LOGDH(" DHencrypt: enc update ret nullptr");
    return nullptr;
  }
  /* Buffer passed to EVP_EncryptFinal() must be after data just
   * encrypted to avoid overwriting it.
   */
  tmplen = 0;

  if (!EVP_EncryptFinal_ex(ctx, ciphertext.get() + outlen, &tmplen)) {
    LOGDH("DHencrypt: enc final ret nullptr");
    return nullptr;
  }

  outlen += tmplen;

  EVP_CIPHER_CTX_free(ctx);

  LOGDH("DHencrypt: in len is %d, out len is %d", len, outlen);

  *retLen = outlen;
  return ciphertext.release();
}

unsigned char *gf_decryptDH(void *dhCtx, const unsigned char *cleartext,
                            int len, int *retLen) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  // Validation
  if (cleartext == nullptr || len < 1 || retLen == nullptr) {
    return nullptr;
  }

  LOGDH(" DH: gf_encryptDH using sk algo: %s, Keysize: %d",
        dhimpl->m_skAlgo.c_str(), dhimpl->m_keySize);

  auto ciphertext = std::unique_ptr<unsigned char[]>(
      new unsigned char[len + 50]);  // give enough room for padding
  int outlen, tmplen;
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();

  auto cipherFunc = dhimpl->getCipherFunc();

  // init openssl cipher context
  if (dhimpl->m_skAlgo == "AES") {
    int keySize = dhimpl->m_keySize > 128 ? dhimpl->m_keySize / 8 : 16;
    EVP_DecryptInit_ex(ctx, cipherFunc, nullptr, dhimpl->m_key,
                       dhimpl->m_key + keySize);
  } else if (dhimpl->m_skAlgo == "Blowfish") {
    int keySize = dhimpl->m_keySize > 128 ? dhimpl->m_keySize / 8 : 16;
    EVP_DecryptInit_ex(ctx, cipherFunc, nullptr, nullptr,
                       dhimpl->m_key + keySize);
    EVP_CIPHER_CTX_set_key_length(ctx, keySize);
    LOGDH("DHencrypt: BF keysize is %d", keySize);
    EVP_DecryptInit_ex(ctx, nullptr, nullptr, dhimpl->m_key, nullptr);
  } else if (dhimpl->m_skAlgo == "DESede") {
    EVP_DecryptInit_ex(ctx, cipherFunc, nullptr, dhimpl->m_key,
                       dhimpl->m_key + 24);
  }

  if (!EVP_DecryptUpdate(ctx, ciphertext.get(), &outlen, cleartext, len)) {
    LOGDH(" DHencrypt: enc update ret nullptr");
    return nullptr;
  }
  /* Buffer passed to EVP_EncryptFinal() must be after data just
   * encrypted to avoid overwriting it.
   */
  tmplen = 0;

  if (!EVP_DecryptFinal_ex(ctx, ciphertext.get() + outlen, &tmplen)) {
    LOGDH("DHencrypt: enc final ret nullptr");
    return nullptr;
  }

  outlen += tmplen;

  EVP_CIPHER_CTX_free(ctx);

  LOGDH("DHencrypt: in len is %d, out len is %d", len, outlen);

  *retLen = outlen;
  return ciphertext.release();
}

// std::shared_ptr<CacheableBytes> decrypt(const uint8_t * ciphertext, int len)
// {
//  LOGDH("DH: Used unimplemented decrypt!");
//  return nullptr;
//}

bool gf_verifyDH(void *dhCtx, const char *subject,
                 const unsigned char *challenge, int challengeLen,
                 const unsigned char *response, int responseLen, int *reason) {
  DHImpl *dhimpl = reinterpret_cast<DHImpl *>(dhCtx);

  LOGDH(" In Verify - looking for subject %s", subject);

  EVP_PKEY *evpkey = nullptr;
  X509 *cert = nullptr;

  char *certsubject = nullptr;

  int32_t count = static_cast<int32_t>(dhimpl->m_serverCerts.size());
  if (count == 0) {
    *reason = DH_ERR_NO_CERTIFICATES;
    return false;
  }

  for (int item = 0; item < count; item++) {
    certsubject = X509_NAME_oneline(
        X509_get_subject_name(dhimpl->m_serverCerts[item]), nullptr, 0);

    // Ignore first letter for comparision, openssl adds / before subject name
    // e.g. /CN=geode1
    if (strcmp(certsubject + 1, subject) == 0) {
      evpkey = X509_get_pubkey(dhimpl->m_serverCerts[item]);
      cert = dhimpl->m_serverCerts[item];
      LOGDH("Found subject [%s] in stored certificates", certsubject);
      break;
    }
  }

  if (evpkey == nullptr || cert == nullptr) {
    *reason = DH_ERR_SUBJECT_NOT_FOUND;
    LOGDH("Certificate not found!");
    return false;
  }

  const ASN1_OBJECT *macobj;
  const X509_ALGOR *algorithm = nullptr;
  X509_ALGOR_get0(&macobj, nullptr, nullptr, algorithm);
  if (algorithm == nullptr) {
    LOGDH("algo is null \n");
  }

  const EVP_MD *signatureDigest = EVP_get_digestbyobj(macobj);
  LOGDH("after EVP_get_digestbyobj  :  err(%d): %s", ERR_get_error(),
        ERR_error_string(ERR_get_error(), nullptr));
  EVP_MD_CTX *signatureCtx = EVP_MD_CTX_new();

  int result1 = EVP_VerifyInit_ex(signatureCtx, signatureDigest, nullptr);
  LOGDH("after EVP_VerifyInit_ex ret %d : err(%d): %s", result1,
        ERR_get_error(), ERR_error_string(ERR_get_error(), nullptr));
  LOGDH(" Result of VerifyInit is %s \n", ERR_lib_error_string(result1));
  LOGDH(" Result of VerifyInit is %s \n", ERR_func_error_string(result1));
  LOGDH(" Result of VerifyInit is %s \n", ERR_reason_error_string(result1));

  LOGDH(" Result of VerifyInit is %d", result1);

  int result2 = EVP_VerifyUpdate(signatureCtx, challenge, challengeLen);
  LOGDH(" Result of VerifyUpdate is %d", result2);

  int result3 = EVP_VerifyFinal(signatureCtx, response, responseLen, evpkey);
  LOGDH(" Result of VerifyFinal is %d", result3);

  bool result = (result1 == 1 && result2 == 1 && result3 == 1);

  EVP_MD_CTX_free(signatureCtx);

  if (result == false) {
    *reason = DH_ERR_INVALID_SIGN;
  }

  return result;
}

int DH_PUBKEY_set(DH_PUBKEY **x, EVP_PKEY *pkey) {
  DH_PUBKEY *pk = nullptr;
  X509_ALGOR *a;
  ASN1_OBJECT *o;
  unsigned char *s, *p = nullptr;
  int i;
  ASN1_INTEGER *asn1int = nullptr;
  DH *dh = EVP_PKEY_get1_DH(pkey);

  if (x == nullptr) return (0);

  if ((pk = DH_PUBKEY_new()) == nullptr) goto err;
  a = pk->algor;

  LOGDH(" key type for OBJ NID is %d", EVP_PKEY_base_id(pkey));

  /* set the algorithm id */
  if ((o = OBJ_nid2obj(EVP_PKEY_base_id(pkey))) == nullptr) goto err;
  ASN1_OBJECT_free(a->algorithm);
  a->algorithm = o;

  /* Set the parameter list */
  if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) {
    if ((a->parameter == nullptr) || (a->parameter->type != V_ASN1_NULL)) {
      ASN1_TYPE_free(a->parameter);
      if (!(a->parameter = ASN1_TYPE_new())) {
        X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
        goto err;
      }
      a->parameter->type = V_ASN1_NULL;
    }
  } else if (EVP_PKEY_base_id(pkey) == EVP_PKEY_DH) {
    unsigned char *pp;
    ASN1_TYPE_free(a->parameter);
    if ((i = i2d_DHparams(dh, nullptr)) <= 0) goto err;
    if (!(p = reinterpret_cast<unsigned char *>(OPENSSL_malloc(i)))) {
      X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
      goto err;
    }
    pp = p;
    i2d_DHparams(dh, &pp);
    if (!(a->parameter = ASN1_TYPE_new())) {
      OPENSSL_free(p);
      X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
      goto err;
    }
    a->parameter->type = V_ASN1_SEQUENCE;
    if (!(a->parameter->value.sequence = ASN1_STRING_new())) {
      OPENSSL_free(p);
      X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
      goto err;
    }
    if (!ASN1_STRING_set(a->parameter->value.sequence, p, i)) {
      OPENSSL_free(p);
      X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
      goto err;
    }
    OPENSSL_free(p);
  } else if (1) {
    X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
    goto err;
  }

  const BIGNUM *pub_key, *priv_key;
  DH_get0_key(dh, &pub_key, &priv_key);

  asn1int = BN_to_ASN1_INTEGER(pub_key, nullptr);
  if ((i = i2d_ASN1_INTEGER(asn1int, nullptr)) <= 0) goto err;
  if ((s = reinterpret_cast<unsigned char *>(OPENSSL_malloc(i + 1))) ==
      nullptr) {
    X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  p = s;
  i2d_ASN1_INTEGER(asn1int, &p);
  if (!ASN1_BIT_STRING_set(static_cast<ASN1_STRING *>(pk->public_key), s, i)) {
    X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
    goto err;
  }
  /* Set number of unused bits to zero */
  pk->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
  pk->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;

  OPENSSL_free(s);

  if (*x != nullptr) DH_PUBKEY_free(*x);

  *x = pk;

  return 1;
err:
  if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
  if (pk != nullptr) DH_PUBKEY_free(pk);
  return 0;
}

EVP_PKEY *DH_PUBKEY_get(DH_PUBKEY *key) {
  EVP_PKEY *ret = nullptr;
  decltype(asn1_string_st::length) j;
  const unsigned char *p;
  const unsigned char *cp;
  X509_ALGOR *a;
  ASN1_INTEGER *asn1int = nullptr;

  if (key == nullptr) {
    if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
    if (ret != nullptr) EVP_PKEY_free(ret);
    return (nullptr);
  }

  if (key->pkey != nullptr) {
    EVP_PKEY_up_ref(key->pkey);
    return (key->pkey);
  }

  if (key->public_key == nullptr) {
    if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
    if (ret != nullptr) EVP_PKEY_free(ret);
    return (nullptr);
  }

  if ((ret = EVP_PKEY_new()) == nullptr) {
    X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE);
    if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
    if (ret != nullptr) EVP_PKEY_free(ret);
    return (nullptr);
  }

  LOGDH(" DHPUBKEY evppkey type is %d", EVP_PKEY_base_id(ret));

  /* the parameters must be extracted before the public key */

  a = key->algor;

  if (EVP_PKEY_base_id(ret) == EVP_PKEY_DH) {
    if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE)) {
      if ((EVP_PKEY_set1_DH(ret, DH_new())) == 0) {
        X509err(X509_F_X509_PUBKEY_DECODE, ERR_R_MALLOC_FAILURE);
        if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
        if (ret != nullptr) EVP_PKEY_free(ret);
        return (nullptr);
      }
      cp = p = a->parameter->value.sequence->data;
      j = a->parameter->value.sequence->length;
      DH *dh = EVP_PKEY_get1_DH(ret);
      if (!d2i_DHparams(&dh, &cp, j)) {
        if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
        if (ret != nullptr) EVP_PKEY_free(ret);
        return (nullptr);
      }
    }
  }

  p = key->public_key->data;
  j = key->public_key->length;

  asn1int = d2i_ASN1_INTEGER(nullptr, &p, j);
  LOGDH("after d2i asn1 integer ptr is %p", asn1int);

  DH *dh = EVP_PKEY_get1_DH(ret);
  DH_set0_key(dh, ASN1_INTEGER_to_BN(asn1int, nullptr), nullptr);
  // LOGDH(" after asn1int to bn ptr is %p", ret->pkey.dh->pub_key);

  key->pkey = ret;
  EVP_PKEY_up_ref(ret);

  if (asn1int != nullptr) ASN1_INTEGER_free(asn1int);
  return (ret);
}
