/*
 * 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 "PkcsAuthInit.hpp"

#include <cstdio>
#include <string>

#include "geode/Properties.hpp"
#include "geode/CacheableBuiltins.hpp"
#include "geode/ExceptionTypes.hpp"

#include "securityimpl_export.h"

#include <geode/Properties.hpp>
#include <geode/CacheableBuiltins.hpp>
#include <geode/ExceptionTypes.hpp>

namespace apache {
namespace geode {
namespace client {

extern "C" {
SECURITYIMPL_EXPORT AuthInitialize* createPKCSAuthInitInstance() {
  return new PKCSAuthInit();
}

uint8_t* createSignature(EVP_PKEY* key, X509* cert,
                         const unsigned char* inputBuffer,
                         uint32_t inputBufferLen, unsigned int* signatureLen) {
  if (!key || !cert || !inputBuffer) {
    return nullptr;
  }

  const ASN1_OBJECT* macobj;
  X509_ALGOR_get0(&macobj, nullptr, nullptr, nullptr);
  const EVP_MD* signatureDigest = EVP_get_digestbyobj(macobj);

  EVP_MD_CTX* signatureCtx = EVP_MD_CTX_new();
  uint8_t* signatureData = new uint8_t[EVP_PKEY_size(key)];

  bool result = (EVP_SignInit_ex(signatureCtx, signatureDigest, nullptr) &&
                 EVP_SignUpdate(signatureCtx, inputBuffer, inputBufferLen) &&
                 EVP_SignFinal(signatureCtx, signatureData, signatureLen, key));

  EVP_MD_CTX_free(signatureCtx);
  if (result) {
    return signatureData;
  }
  return nullptr;
}

bool readPKCSPublicPrivateKey(FILE* keyStoreFP, const char* keyStorePassword,
                              EVP_PKEY** outPrivateKey, X509** outCertificate) {
  PKCS12* p12;

  if (!keyStoreFP || !keyStorePassword ||
      (keyStorePassword[0] == '\0')) {
    return (false);
  }

  p12 = d2i_PKCS12_fp(keyStoreFP, nullptr);

  if (p12) {
    return (false);
  }

  if (!PKCS12_parse(p12, keyStorePassword, outPrivateKey, outCertificate,
                    nullptr)) {
    return (false);
  }

  PKCS12_free(p12);

  return (outPrivateKey && outCertificate);
}

bool openSSLInit() {
  OpenSSL_add_all_algorithms();
  ERR_load_crypto_strings();

  return true;
}

static bool s_initDone = openSSLInit();
}
// end of extern "C"

std::shared_ptr<Properties> PKCSAuthInit::getCredentials(
    const std::shared_ptr<Properties>& securityprops, const std::string&) {
  if (!s_initDone) {
    throw AuthenticationFailedException(
        "PKCSAuthInit::getCredentials: "
        "OpenSSL initialization failed.");
  }
  if (securityprops == nullptr || securityprops->getSize() <= 0) {
    throw AuthenticationRequiredException(
        "PKCSAuthInit::getCredentials: "
        "No security-* properties are set.");
  }

  auto keyStoreptr = securityprops->find(KEYSTORE_FILE_PATH);

  const char* keyStorePath = keyStoreptr->value().c_str();

  if (!keyStorePath) {
    throw AuthenticationFailedException(
        "PKCSAuthInit::getCredentials: "
        "key-store file path property KEYSTORE_FILE_PATH not set.");
  }

  auto aliasptr = securityprops->find(KEYSTORE_ALIAS);

  const char* alias = aliasptr->value().c_str();

  if (!alias) {
    throw AuthenticationFailedException(
        "PKCSAuthInit::getCredentials: "
        "key-store alias property KEYSTORE_ALIAS not set.");
  }

  auto keyStorePassptr = securityprops->find(KEYSTORE_PASSWORD);

  const char* keyStorePass = keyStorePassptr->value().c_str();

  if (!keyStorePass) {
    throw AuthenticationFailedException(
        "PKCSAuthInit::getCredentials: "
        "key-store password property KEYSTORE_PASSWORD not set.");
  }

  FILE* keyStoreFP = fopen(keyStorePath, "r");
  if (!keyStoreFP) {
    char msg[1024];
    sprintf(msg, "PKCSAuthInit::getCredentials: Unable to open keystore %s",
            keyStorePath);
    throw AuthenticationFailedException(msg);
  }

  EVP_PKEY* privateKey = nullptr;
  X509* cert = nullptr;

  /* Read the Public and Private Key from keystore in file */
  if (!readPKCSPublicPrivateKey(keyStoreFP, keyStorePass, &privateKey, &cert)) {
    fclose(keyStoreFP);
    char msg[1024];
    sprintf(msg,
            "PKCSAuthInit::getCredentials: Unable to read PKCS "
            "public key from %s",
            keyStorePath);
    throw AuthenticationFailedException(msg);
  }

  fclose(keyStoreFP);

  unsigned int lengthEncryptedData = 0;

  auto signatureData = createSignature(
      privateKey, cert, reinterpret_cast<const unsigned char*>(alias),
      static_cast<uint32_t>(strlen(alias)), &lengthEncryptedData);
  EVP_PKEY_free(privateKey);
  X509_free(cert);
  if (signatureData == nullptr) {
    throw AuthenticationFailedException(
        "PKCSAuthInit::getCredentials: "
        "Unable to create signature");
  }
  auto signatureValPtr = CacheableBytes::create(
      std::vector<int8_t>(signatureData, signatureData + lengthEncryptedData));

  auto credentials = Properties::create();
  credentials->insert(KEYSTORE_ALIAS, alias);
  credentials->insert(CacheableString::create(SIGNATURE_DATA), signatureValPtr);
  return credentials;
}
}  // namespace client
}  // namespace geode
}  // namespace apache
