/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2014 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 *
 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
 * @author Jeff Thompson <jefft0@remap.ucla.edu>
 */

#include "common.hpp"

#include "validator.hpp"
#include "../util/crypto.hpp"

#include "cryptopp.hpp"

namespace ndn {

static OID SECP256R1("1.2.840.10045.3.1.7");
static OID SECP384R1("1.3.132.0.34");

Validator::Validator()
  : m_hasFace(false)
  , m_face(*static_cast<Face*>(0))
{
}

Validator::Validator(Face& face)
  : m_hasFace(true)
  , m_face(face)
{
}

void
Validator::validate(const Interest& interest,
                    const OnInterestValidated& onValidated,
                    const OnInterestValidationFailed& onValidationFailed,
                    int nSteps)
{
  std::vector<shared_ptr<ValidationRequest> > nextSteps;
  checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);

  if (!nextSteps.empty())
    {
      if (!m_hasFace)
        {
          onValidationFailed(interest.shared_from_this(),
                             "Require more information to validate the interest!");
          return;
        }

      std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
      OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
      for (; it != nextSteps.end(); it++)
        m_face.expressInterest((*it)->m_interest,
                               bind(&Validator::onData, this, _1, _2, *it),
                               bind(&Validator::onTimeout,
                                    this, _1, (*it)->m_nRetrials,
                                    onFailure,
                                    *it));
    }
  else
    {
      // If there is no nextStep,
      // that means InterestPolicy has already been able to verify the Interest.
      // No more further processes.
    }
}

void
Validator::validate(const Data& data,
                    const OnDataValidated& onValidated,
                    const OnDataValidationFailed& onValidationFailed,
                    int nSteps)
{
  std::vector<shared_ptr<ValidationRequest> > nextSteps;
  checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);

  if (!nextSteps.empty())
    {
      if (!m_hasFace)
        {
          onValidationFailed(data.shared_from_this(),
                             "Require more information to validate the data!");
        }

      std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
      OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
      for (; it != nextSteps.end(); it++)
        m_face.expressInterest((*it)->m_interest,
                               bind(&Validator::onData, this, _1, _2, *it),
                               bind(&Validator::onTimeout,
                                    this, _1, (*it)->m_nRetrials,
                                    onFailure,
                                    *it));
    }
  else
    {
      // If there is no nextStep,
      // that means Data Policy has already been able to verify the Interest.
      // No more further processes.
    }
}

void
Validator::onData(const Interest& interest,
                  const Data& data,
                  const shared_ptr<ValidationRequest>& nextStep)
{
  validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_nSteps);
}

void
Validator::onTimeout(const Interest& interest,
                     int nRetrials,
                     const OnFailure& onFailure,
                     const shared_ptr<ValidationRequest>& nextStep)
{
  if (nRetrials > 0)
    // Issue the same expressInterest except decrement nRetrials.
    m_face.expressInterest(interest,
                            bind(&Validator::onData, this, _1, _2, nextStep),
                            bind(&Validator::onTimeout, this, _1,
                                 nRetrials - 1, onFailure, nextStep));
  else
    onFailure("Cannot fetch cert: " + interest.getName().toUri());
}

bool
Validator::verifySignature(const Data& data, const PublicKey& key)
{
  try
    {
      switch (data.getSignature().getType())
        {
        case Tlv::SignatureSha256WithRsa:
          {
            SignatureSha256WithRsa sigSha256Rsa(data.getSignature());
            return verifySignature(data.wireEncode().value(),
                                   data.wireEncode().value_size() -
                                   data.getSignature().getValue().size(),
                                   sigSha256Rsa, key);
          }
        case Tlv::SignatureSha256WithEcdsa:
          {
            SignatureSha256WithEcdsa sigSha256Ecdsa(data.getSignature());
            return verifySignature(data.wireEncode().value(),
                                   data.wireEncode().value_size() -
                                   data.getSignature().getValue().size(),
                                   sigSha256Ecdsa, key);
           }
        default:
          {
            // Unsupported sig type
            return false;
          }
        }
    }
  catch (Signature::Error& e)
    {
      return false;
    }
  return false;
}

bool
Validator::verifySignature(const Interest& interest, const PublicKey& key)
{
  const Name& interestName = interest.getName();

  if (interestName.size() < 2)
    return false;

  try
    {
      const Block& nameBlock = interestName.wireEncode();

      Signature sig(interestName[-2].blockFromValue(),
                    interestName[-1].blockFromValue());

      switch (sig.getType())
        {
        case Tlv::SignatureSha256WithRsa:
          {
            SignatureSha256WithRsa sigSha256Rsa(sig);

            return verifySignature(nameBlock.value(),
                                   nameBlock.value_size() - interestName[-1].size(),
                                   sigSha256Rsa, key);
          }
        case Tlv::SignatureSha256WithEcdsa:
          {
            SignatureSha256WithEcdsa sigSha256Ecdsa(sig);

            return verifySignature(nameBlock.value(),
                                   nameBlock.value_size() - interestName[-1].size(),
                                   sigSha256Ecdsa, key);
          }
        default:
          {
            // Unsupported sig type
            return false;
          }
        }
    }
  catch (Signature::Error& e)
    {
      return false;
    }
  catch (Block::Error& e)
    {
      return false;
    }
  return false;
}

bool
Validator::verifySignature(const uint8_t* buf,
                           const size_t size,
                           const SignatureWithPublicKey& sig,
                           const PublicKey& key)
{
  try
    {
      using namespace CryptoPP;

      switch (sig.getType())
        {
        case Tlv::SignatureSha256WithRsa:
          {
            if (key.getKeyType() != KEY_TYPE_RSA)
              return false;

            RSA::PublicKey publicKey;
            ByteQueue queue;

            queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
            publicKey.Load(queue);

            RSASS<PKCS1v15, SHA256>::Verifier verifier(publicKey);
            return verifier.VerifyMessage(buf, size,
                                          sig.getValue().value(), sig.getValue().value_size());
          }
        case Tlv::SignatureSha256WithEcdsa:
          {
            if (key.getKeyType() != KEY_TYPE_ECDSA)
              return false;

            ECDSA<ECP, SHA256>::PublicKey publicKey;
            ByteQueue queue;

            queue.Put(reinterpret_cast<const byte*>(key.get().buf()), key.get().size());
            publicKey.Load(queue);

            ECDSA<ECP, SHA256>::Verifier verifier(publicKey);

            uint32_t length = 0;
            StringSource src(key.get().buf(), key.get().size(), true);
            BERSequenceDecoder subjectPublicKeyInfo(src);
            {
              BERSequenceDecoder algorithmInfo(subjectPublicKeyInfo);
              {
                OID algorithm;
                algorithm.decode(algorithmInfo);

                OID curveId;
                curveId.decode(algorithmInfo);

                if (curveId == SECP256R1)
                  length = 256;
                else if (curveId == SECP384R1)
                  length = 384;
                else
                  return false;
              }
            }

            switch (length)
              {
              case 256:
                {
                  uint8_t buffer[64];
                  size_t usedSize = DSAConvertSignatureFormat(buffer, 64, DSA_P1363,
                                                              sig.getValue().value(),
                                                              sig.getValue().value_size(),
                                                              DSA_DER);
                  return verifier.VerifyMessage(buf, size, buffer, usedSize);
                }
              case 384:
                {
                  uint8_t buffer[96];
                  size_t usedSize = DSAConvertSignatureFormat(buffer, 96, DSA_P1363,
                                                              sig.getValue().value(),
                                                              sig.getValue().value_size(),
                                                              DSA_DER);
                  return verifier.VerifyMessage(buf, size, buffer, usedSize);
                }
              default:
                return false;
              }
          }
        default:
          // Unsupported sig type
          return false;
        }
    }
  catch (CryptoPP::Exception& e)
    {
      return false;
    }
}

bool
Validator::verifySignature(const uint8_t* buf, const size_t size, const DigestSha256& sig)
{
  try
    {
      ConstBufferPtr buffer = crypto::sha256(buf, size);
      const Block& sigValue = sig.getValue();

      if (static_cast<bool>(buffer) &&
          buffer->size() == sigValue.value_size() &&
          buffer->size() == crypto::SHA256_DIGEST_SIZE)
        {

          const uint8_t* p1 = buffer->buf();
          const uint8_t* p2 = sigValue.value();

          return 0 == memcmp(p1, p2, crypto::SHA256_DIGEST_SIZE);
        }
      else
        return false;
    }
  catch (CryptoPP::Exception& e)
    {
      return false;
    }
}

} // namespace ndn
