//========================================================================
//
// SignatureHandler.cc
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2015, 2016 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
// Copyright 2015, 2016, 2018, 2019 Albert Astals Cid <aacid@kde.org>
// Copyright 2015 Markus Kilås <digital@markuspage.com>
// Copyright 2017 Sebastian Rasmussen <sebras@gmail.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
// Copyright 2018 Oliver Sander <oliver.sander@tu-dresden.de>
//
//========================================================================

#include <config.h>

#include "SignatureHandler.h"
#include "goo/gmem.h"
#include <secmod.h>
#include <keyhi.h>
#include <secder.h>

#include <dirent.h>
#include <Error.h>

unsigned int SignatureHandler::digestLength(SECOidTag digestAlgId)
{
  switch(digestAlgId){
    case SEC_OID_SHA1:
      return 20;
    case SEC_OID_SHA256:
      return 32;
    case SEC_OID_SHA384:
      return 48;
    case SEC_OID_SHA512:
      return 64;
    default:
      printf("ERROR: Unrecognized Hash ID\n");
      return 0;
  }
}

char *SignatureHandler::getSignerName()
{
  if (!CMSSignerInfo || !NSS_IsInitialized())
      return nullptr;

  CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB());
  return CERT_GetCommonName(&cert->subject);
}

const char * SignatureHandler::getSignerSubjectDN()
{
  if (!CMSSignerInfo)
    return nullptr;

  CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB());
  if (!cert)
    return nullptr;
  return cert->subjectName;
}

HASH_HashType SignatureHandler::getHashAlgorithm()
{
  if (hash_context && hash_context->hashobj)
  {
    return hash_context->hashobj->type;
  }
  return HASH_AlgNULL;
}

time_t SignatureHandler::getSigningTime()
{
  PRTime sTime; // time in microseconds since the epoch

  if (NSS_CMSSignerInfo_GetSigningTime (CMSSignerInfo, &sTime) != SECSuccess)
    return 0;

  return static_cast<time_t>(sTime/1000000);
}

X509CertificateInfo::EntityInfo SignatureHandler::getEntityInfo(CERTName *entityName) const
{
  X509CertificateInfo::EntityInfo info;

  if (!entityName)
    return info;

  char *dn = CERT_NameToAscii(entityName);
  if (dn) {
      info.distinguishedName = dn;
      PORT_Free(dn);
  }

  char *cn = CERT_GetCommonName(entityName);
  if (cn) {
    info.commonName = cn;
    PORT_Free(cn);
  }

  char *email = CERT_GetCertEmailAddress(entityName);
  if (email) {
    info.email = email;
    PORT_Free(email);
  }

  char *org = CERT_GetOrgName(entityName);
  if (org) {
    info.organization = org;
    PORT_Free(org);
  }

  return info;
}

static GooString SECItemToGooString(const SECItem &secItem)
{
  // TODO do we need to handle secItem.type;
  return GooString((const char *)secItem.data, secItem.len);
}

std::unique_ptr<X509CertificateInfo> SignatureHandler::getCertificateInfo() const
{
  if (!CMSSignerInfo)
    return nullptr;

  CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB());
  if (!cert)
    return nullptr;

  auto certInfo = std::make_unique<X509CertificateInfo>();

  certInfo->setVersion(DER_GetInteger(&cert->version) + 1);
  certInfo->setSerialNumber(SECItemToGooString(cert->serialNumber));

  //issuer info
  certInfo->setIssuerInfo(getEntityInfo(&cert->issuer));

  //validity
  PRTime notBefore, notAfter;
  CERT_GetCertTimes(cert, &notBefore, &notAfter);
  X509CertificateInfo::Validity certValidity;
  certValidity.notBefore = static_cast<time_t>(notBefore/1000000);
  certValidity.notAfter = static_cast<time_t>(notAfter/1000000);
  certInfo->setValidity(certValidity);

  //subject info
  certInfo->setSubjectInfo(getEntityInfo(&cert->subject));

  //public key info
  X509CertificateInfo::PublicKeyInfo pkInfo;
  SECKEYPublicKey *pk = CERT_ExtractPublicKey(cert);
  switch (pk->keyType)
  {
    case rsaKey:
      pkInfo.publicKey = SECItemToGooString(pk->u.rsa.modulus);
      pkInfo.publicKeyType = RSAKEY;
      break;
    case dsaKey:
      pkInfo.publicKey = SECItemToGooString(pk->u.dsa.publicValue);
      pkInfo.publicKeyType = DSAKEY;
      break;
    case ecKey:
      pkInfo.publicKey = SECItemToGooString(pk->u.ec.publicValue);
      pkInfo.publicKeyType = ECKEY;
      break;
    default:
      pkInfo.publicKey = SECItemToGooString(cert->subjectPublicKeyInfo.subjectPublicKey);
      pkInfo.publicKeyType = OTHERKEY;
      break;
  }
  pkInfo.publicKeyStrength = SECKEY_PublicKeyStrengthInBits(pk);
  certInfo->setPublicKeyInfo(std::move(pkInfo));

  certInfo->setKeyUsageExtensions(cert->keyUsage);
  certInfo->setCertificateDER(SECItemToGooString(cert->derCert));
  certInfo->setIsSelfSigned(CERT_CompareName(&cert->subject, &cert->issuer) == SECEqual);

  return certInfo;
}

static GooString *getDefaultFirefoxCertDB_Linux()
{
  GooString * finalPath = nullptr;
  DIR *toSearchIn;
  struct dirent *subFolder;

  GooString * homePath = new GooString(getenv("HOME"));
  homePath = homePath->append("/.mozilla/firefox/");

  if ((toSearchIn = opendir(homePath->c_str())) == nullptr) {
    error(errInternal, 0, "couldn't find default Firefox Folder");
    delete homePath;
    return nullptr;
  }
  do {
    if ((subFolder = readdir(toSearchIn)) != nullptr) {
      if (strstr(subFolder->d_name, "default") != nullptr) {
        finalPath = homePath->append(subFolder->d_name);
        closedir(toSearchIn);
        return finalPath;
      }
    }
  } while (subFolder != nullptr);

  closedir(toSearchIn);
  delete homePath;
  return nullptr;
}

/**
 * Initialise NSS
 */
void SignatureHandler::setNSSDir(const GooString &nssDir)
{
  static bool setNssDirCalled = false;

  if (NSS_IsInitialized() && nssDir.getLength() > 0) {
    error(errInternal, 0, "You need to call setNSSDir before signature validation related operations happen");
    return;
  }

  if (setNssDirCalled)
    return;

  setNssDirCalled = true;

  bool initSuccess = false;
  if (nssDir.getLength() > 0) {
    initSuccess = (NSS_Init(nssDir.c_str()) == SECSuccess);
  } else {
    GooString *certDBPath = getDefaultFirefoxCertDB_Linux();
    if (certDBPath == nullptr) {
      initSuccess = (NSS_Init("sql:/etc/pki/nssdb") == SECSuccess);
    } else {
      initSuccess = (NSS_Init(certDBPath->c_str()) == SECSuccess);
    }
    if (!initSuccess) {
      GooString homeNssDb(getenv("HOME"));
      homeNssDb.append("/.pki/nssdb");
      initSuccess = (NSS_Init(homeNssDb.c_str()) == SECSuccess);
      if (!initSuccess) {
	NSS_NoDB_Init(nullptr);
      }
    }
    delete certDBPath;
  }

  if (initSuccess) {
    //Make sure NSS root certificates module is loaded
    SECMOD_AddNewModule("Root Certs", "libnssckbi.so", 0, 0);
  }
}


SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length)
 : hash_context(nullptr),
   CMSMessage(nullptr),
   CMSSignedData(nullptr),
   CMSSignerInfo(nullptr),
   temp_certs(nullptr)
{
  setNSSDir({});
  CMSitem.data = p7;
  CMSitem.len = p7_length;
  CMSMessage = CMS_MessageCreate(&CMSitem);
  CMSSignedData = CMS_SignedDataCreate(CMSMessage);
  if (CMSSignedData) {
    CMSSignerInfo = CMS_SignerInfoCreate(CMSSignedData);
    hash_context = initHashContext();
  }
}

HASHContext * SignatureHandler::initHashContext()
{

  SECItem usedAlgorithm = NSS_CMSSignedData_GetDigestAlgs(CMSSignedData)[0]->algorithm;
  hash_length = digestLength(SECOID_FindOIDTag(&usedAlgorithm));
  HASH_HashType hashType;
  hashType    = HASH_GetHashTypeByOidTag(SECOID_FindOIDTag(&usedAlgorithm));
  return HASH_Create(hashType);
}

void SignatureHandler::updateHash(unsigned char * data_block, int data_len)
{
  if (hash_context) {
    HASH_Update(hash_context, data_block, data_len);
  }
}

SignatureHandler::~SignatureHandler()
{
  SECITEM_FreeItem(&CMSitem, PR_FALSE);
  if (CMSMessage)
    NSS_CMSMessage_Destroy(CMSMessage);

  if (hash_context)
    HASH_Destroy(hash_context);

  free(temp_certs);

  if (NSS_Shutdown()!=SECSuccess)
    fprintf(stderr, "Detail: %s\n", PR_ErrorToString(PORT_GetError(), PR_LANGUAGE_I_DEFAULT));
}

NSSCMSMessage *SignatureHandler::CMS_MessageCreate(SECItem * cms_item)
{
  if (cms_item->data){
    return NSS_CMSMessage_CreateFromDER(cms_item, nullptr, nullptr /* Content callback */
                        , nullptr, nullptr /*Password callback*/
                        , nullptr, nullptr /*Decrypt callback*/);
  } else {
    return nullptr;
  }
}

NSSCMSSignedData *SignatureHandler::CMS_SignedDataCreate(NSSCMSMessage * cms_msg)
{
  if (!NSS_CMSMessage_IsSigned(cms_msg)) {
    error(errInternal, 0, "Input couldn't be parsed as a CMS signature");
    return nullptr;
  }

  NSSCMSContentInfo *cinfo = NSS_CMSMessage_ContentLevel(cms_msg, 0);
  if (!cinfo) {
    error(errInternal, 0, "Error in NSS_CMSMessage_ContentLevel");
    return nullptr;
  }

  NSSCMSSignedData *signedData = (NSSCMSSignedData*) NSS_CMSContentInfo_GetContent(cinfo);
  if (!signedData) {
    error(errInternal, 0, "CError in NSS_CMSContentInfo_GetContent()");
    return nullptr;
  }

  if (signedData->rawCerts)
  {
    size_t i;
    for (i = 0; signedData->rawCerts[i]; ++i) {} // just count the length of the certificate chain

    // tempCerts field needs to be filled for complete memory release by NSSCMSSignedData_Destroy
    signedData->tempCerts = (CERTCertificate **) gmallocn( i+1, sizeof(CERTCertificate *));
    memset(signedData->tempCerts, 0, (i+1) * sizeof(CERTCertificate *));
    // store the addresses of these temporary certificates for future release
    for (i = 0; signedData->rawCerts[i]; ++i)
      signedData->tempCerts[i] = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), signedData->rawCerts[i], nullptr, 0, 0);

    temp_certs = signedData->tempCerts;
    return signedData;
  } else {
    return nullptr;
  }
}

NSSCMSSignerInfo *SignatureHandler::CMS_SignerInfoCreate(NSSCMSSignedData * cms_sig_data)
{
  NSSCMSSignerInfo *signerInfo = NSS_CMSSignedData_GetSignerInfo(cms_sig_data, 0);
  if (!signerInfo) {
    printf("Error in NSS_CMSSignedData_GetSignerInfo()\n");
    return nullptr;
  } else {
    return signerInfo;
  }
}

static SignatureValidationStatus NSS_SigTranslate(NSSCMSVerificationStatus nss_code)
{
  switch(nss_code)
  {
    case NSSCMSVS_GoodSignature:
      return SIGNATURE_VALID;

    case NSSCMSVS_BadSignature:
      return SIGNATURE_INVALID;

    case NSSCMSVS_DigestMismatch:
      return SIGNATURE_DIGEST_MISMATCH;

    case NSSCMSVS_ProcessingError:
      return SIGNATURE_DECODING_ERROR;

    default:
      return SIGNATURE_GENERIC_ERROR;
  }
}

SignatureValidationStatus SignatureHandler::validateSignature()
{
  unsigned char *digest_buffer = nullptr;

  if (!CMSSignedData)
    return SIGNATURE_GENERIC_ERROR;

  if (!NSS_IsInitialized())
    return SIGNATURE_GENERIC_ERROR;

  digest_buffer = (unsigned char *)PORT_Alloc(hash_length);
  unsigned int result_len = 0;

  HASH_End(hash_context, digest_buffer, &result_len, hash_length);

  SECItem digest;
  digest.data = digest_buffer;
  digest.len = hash_length;

  if ((NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB())) == nullptr)
    CMSSignerInfo->verificationStatus = NSSCMSVS_SigningCertNotFound;

  SECItem * content_info_data = CMSSignedData->contentInfo.content.data;
  if (content_info_data != nullptr && content_info_data->data != nullptr)
  {
    /*
      This means it's not a detached type signature
      so the digest is contained in SignedData->contentInfo
    */
    if (memcmp(digest.data, content_info_data->data, hash_length) == 0
        && digest.len == content_info_data->len)
    {
      PORT_Free(digest_buffer);
      return SIGNATURE_VALID;
    }
    else
    {
      PORT_Free(digest_buffer);
      return SIGNATURE_DIGEST_MISMATCH;
    }

  }
  else if (NSS_CMSSignerInfo_Verify(CMSSignerInfo, &digest, nullptr) != SECSuccess)
  {

    PORT_Free(digest_buffer);
    return NSS_SigTranslate(CMSSignerInfo->verificationStatus);
  }
  else
  {
    PORT_Free(digest_buffer);
    return SIGNATURE_VALID;
  }
}

CertificateValidationStatus SignatureHandler::validateCertificate(time_t validation_time)
{
  CERTCertificate *cert;

  if (!CMSSignerInfo)
    return CERTIFICATE_GENERIC_ERROR;

  if ((cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB())) == nullptr)
    CMSSignerInfo->verificationStatus = NSSCMSVS_SigningCertNotFound;

  PRTime vTime = 0; // time in microseconds since the epoch, special value 0 means now
  if (validation_time > 0)
    vTime = 1000000*(PRTime)validation_time;
  CERTValInParam inParams[3];
  inParams[0].type = cert_pi_revocationFlags;
  inParams[0].value.pointer.revocation = CERT_GetClassicOCSPEnabledSoftFailurePolicy();
  inParams[1].type = cert_pi_date;
  inParams[1].value.scalar.time = vTime;
  inParams[2].type = cert_pi_end;

  CERT_PKIXVerifyCert(cert, certificateUsageEmailSigner, inParams, nullptr,
                CMSSignerInfo->cmsg->pwfn_arg);

  switch(PORT_GetError())
  {
    // 0 not defined in SECErrorCodes, it means success for this purpose.
    case 0:
      return CERTIFICATE_TRUSTED;

    case SEC_ERROR_UNKNOWN_ISSUER:
      return CERTIFICATE_UNKNOWN_ISSUER;

    case SEC_ERROR_UNTRUSTED_ISSUER:
      return CERTIFICATE_UNTRUSTED_ISSUER;

    case SEC_ERROR_REVOKED_CERTIFICATE:
      return CERTIFICATE_REVOKED;

    case SEC_ERROR_EXPIRED_CERTIFICATE:
      return CERTIFICATE_EXPIRED;
  }

  return CERTIFICATE_GENERIC_ERROR;
}
