// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/signature_verifier.h"

#include <openssl/evp.h>
#include <openssl/x509.h>
#include <stdint.h>

#include <vector>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/openssl_util.h"
#include "crypto/scoped_openssl_types.h"

namespace crypto {

namespace {

const EVP_MD* ToOpenSSLDigest(SignatureVerifier::HashAlgorithm hash_alg) {
  switch (hash_alg) {
    case SignatureVerifier::SHA1:
      return EVP_sha1();
    case SignatureVerifier::SHA256:
      return EVP_sha256();
  }
  return NULL;
}

}  // namespace

struct SignatureVerifier::VerifyContext {
  ScopedEVP_MD_CTX ctx;
};

SignatureVerifier::SignatureVerifier()
    : verify_context_(NULL) {
}

SignatureVerifier::~SignatureVerifier() {
  Reset();
}

bool SignatureVerifier::VerifyInit(const uint8_t* signature_algorithm,
                                   int signature_algorithm_len,
                                   const uint8_t* signature,
                                   int signature_len,
                                   const uint8_t* public_key_info,
                                   int public_key_info_len) {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  ScopedOpenSSL<X509_ALGOR, X509_ALGOR_free> algorithm(
      d2i_X509_ALGOR(NULL, &signature_algorithm, signature_algorithm_len));
  if (!algorithm.get())
    return false;
  int nid = OBJ_obj2nid(algorithm.get()->algorithm);
  const EVP_MD* digest;
  if (nid == NID_ecdsa_with_SHA1) {
    digest = EVP_sha1();
  } else if (nid == NID_ecdsa_with_SHA256) {
    digest = EVP_sha256();
  } else {
    // This works for PKCS #1 v1.5 RSA signatures, but not for ECDSA
    // signatures.
    digest = EVP_get_digestbyobj(algorithm.get()->algorithm);
  }
  if (!digest)
    return false;

  return CommonInit(digest, signature, signature_len, public_key_info,
                    public_key_info_len, NULL);
}

bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
                                         HashAlgorithm mask_hash_alg,
                                         int salt_len,
                                         const uint8_t* signature,
                                         int signature_len,
                                         const uint8_t* public_key_info,
                                         int public_key_info_len) {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  const EVP_MD* const digest = ToOpenSSLDigest(hash_alg);
  DCHECK(digest);
  if (!digest) {
    return false;
  }

  EVP_PKEY_CTX* pkey_ctx;
  if (!CommonInit(digest, signature, signature_len, public_key_info,
                  public_key_info_len, &pkey_ctx)) {
    return false;
  }

  int rv = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING);
  if (rv != 1)
    return false;
  const EVP_MD* const mgf_digest = ToOpenSSLDigest(mask_hash_alg);
  DCHECK(mgf_digest);
  if (!mgf_digest) {
    return false;
  }
  rv = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf_digest);
  if (rv != 1)
    return false;
  rv = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len);
  return rv == 1;
}

void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
                                     int data_part_len) {
  DCHECK(verify_context_);
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  int rv = EVP_DigestVerifyUpdate(verify_context_->ctx.get(),
                                  data_part, data_part_len);
  DCHECK_EQ(rv, 1);
}

bool SignatureVerifier::VerifyFinal() {
  DCHECK(verify_context_);
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  int rv = EVP_DigestVerifyFinal(verify_context_->ctx.get(), signature_.data(),
                                 signature_.size());
  DCHECK_EQ(static_cast<int>(!!rv), rv);
  Reset();
  return rv == 1;
}

bool SignatureVerifier::CommonInit(const EVP_MD* digest,
                                   const uint8_t* signature,
                                   int signature_len,
                                   const uint8_t* public_key_info,
                                   int public_key_info_len,
                                   EVP_PKEY_CTX** pkey_ctx) {
  if (verify_context_)
    return false;

  verify_context_ = new VerifyContext;

  signature_.assign(signature, signature + signature_len);

  const uint8_t* ptr = public_key_info;
  ScopedEVP_PKEY public_key(d2i_PUBKEY(nullptr, &ptr, public_key_info_len));
  if (!public_key.get() || ptr != public_key_info + public_key_info_len)
    return false;

  verify_context_->ctx.reset(EVP_MD_CTX_create());
  int rv = EVP_DigestVerifyInit(verify_context_->ctx.get(), pkey_ctx,
                                digest, nullptr, public_key.get());
  return rv == 1;
}

void SignatureVerifier::Reset() {
  delete verify_context_;
  verify_context_ = NULL;
  signature_.clear();
}

}  // namespace crypto
