/*
 * 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/CacheableBuiltins.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/Properties.hpp>

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

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
