// Copyright 2018 Google Inc.
//
// Licensed 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 "tink/signature/signature_key_templates.h"

#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "openssl/bn.h"
#include "openssl/rsa.h"
#include "tink/subtle/subtle_util_boringssl.h"
#include "tink/util/constants.h"
#include "proto/common.pb.h"
#include "proto/ecdsa.pb.h"
#include "proto/ed25519.pb.h"
#include "proto/rsa_ssa_pkcs1.pb.h"
#include "proto/rsa_ssa_pss.pb.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {
namespace {

using google::crypto::tink::EcdsaKeyFormat;
using google::crypto::tink::EcdsaPrivateKey;
using google::crypto::tink::EcdsaSignatureEncoding;
using google::crypto::tink::Ed25519PrivateKey;
using google::crypto::tink::EllipticCurveType;
using google::crypto::tink::HashType;
using google::crypto::tink::KeyTemplate;
using google::crypto::tink::OutputPrefixType;
using google::crypto::tink::RsaSsaPkcs1KeyFormat;
using google::crypto::tink::RsaSsaPkcs1PrivateKey;
using google::crypto::tink::RsaSsaPssKeyFormat;
using google::crypto::tink::RsaSsaPssPrivateKey;

std::unique_ptr<KeyTemplate> NewEcdsaKeyTemplate(
    HashType hash_type, EllipticCurveType curve_type,
    EcdsaSignatureEncoding encoding) {
  auto key_template = absl::make_unique<KeyTemplate>();
  key_template->set_type_url(
      absl::StrCat(kTypeGoogleapisCom, EcdsaPrivateKey().GetTypeName()));
  key_template->set_output_prefix_type(OutputPrefixType::TINK);
  EcdsaKeyFormat key_format;
  auto params = key_format.mutable_params();
  params->set_hash_type(hash_type);
  params->set_curve(curve_type);
  params->set_encoding(encoding);
  key_format.SerializeToString(key_template->mutable_value());
  return key_template;
}

std::unique_ptr<KeyTemplate> NewRsaSsaPkcs1KeyTemplate(HashType hash_type,
                                                       int modulus_size_in_bits,
                                                       int public_exponent) {
  auto key_template = absl::make_unique<KeyTemplate>();
  key_template->set_type_url(
      absl::StrCat(kTypeGoogleapisCom, RsaSsaPkcs1PrivateKey().GetTypeName()));
  key_template->set_output_prefix_type(OutputPrefixType::TINK);
  RsaSsaPkcs1KeyFormat key_format;
  auto params = key_format.mutable_params();
  params->set_hash_type(hash_type);
  key_format.set_modulus_size_in_bits(modulus_size_in_bits);
  bssl::UniquePtr<BIGNUM> e(BN_new());
  BN_set_word(e.get(), public_exponent);
  key_format.set_public_exponent(
      subtle::SubtleUtilBoringSSL::bn2str(e.get(), BN_num_bytes(e.get()))
          .ValueOrDie());
  key_format.SerializeToString(key_template->mutable_value());
  return key_template;
}

std::unique_ptr<KeyTemplate> NewRsaSsaPssKeyTemplate(HashType sig_hash,
                                                     HashType mgf1_hash,
                                                     int salt_length,
                                                     int modulus_size_in_bits,
                                                     int public_exponent) {
  auto key_template = absl::make_unique<KeyTemplate>();
  key_template->set_type_url(
      absl::StrCat(kTypeGoogleapisCom, RsaSsaPssPrivateKey().GetTypeName()));
  key_template->set_output_prefix_type(OutputPrefixType::TINK);
  RsaSsaPssKeyFormat key_format;
  auto params = key_format.mutable_params();
  params->set_sig_hash(sig_hash);
  params->set_mgf1_hash(mgf1_hash);
  params->set_salt_length(salt_length);
  key_format.set_modulus_size_in_bits(modulus_size_in_bits);
  bssl::UniquePtr<BIGNUM> e(BN_new());
  BN_set_word(e.get(), public_exponent);
  key_format.set_public_exponent(
      subtle::SubtleUtilBoringSSL::bn2str(e.get(), BN_num_bytes(e.get()))
          .ValueOrDie());
  key_format.SerializeToString(key_template->mutable_value());
  return key_template;
}

}  // anonymous namespace

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP256() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA256, EllipticCurveType::NIST_P256,
                          EcdsaSignatureEncoding::DER)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP384() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P384,
                          EcdsaSignatureEncoding::DER)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP521() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P521,
                          EcdsaSignatureEncoding::DER)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP256Ieee() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA256, EllipticCurveType::NIST_P256,
                          EcdsaSignatureEncoding::IEEE_P1363)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP384Ieee() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P384,
                          EcdsaSignatureEncoding::IEEE_P1363)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::EcdsaP521Ieee() {
  static const KeyTemplate* key_template =
      NewEcdsaKeyTemplate(HashType::SHA512, EllipticCurveType::NIST_P521,
                          EcdsaSignatureEncoding::IEEE_P1363)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4() {
  static const KeyTemplate* key_template =
      NewRsaSsaPkcs1KeyTemplate(HashType::SHA256, 3072, RSA_F4).release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4() {
  static const KeyTemplate* key_template =
      NewRsaSsaPkcs1KeyTemplate(HashType::SHA512, 4096, RSA_F4).release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4() {
  static const KeyTemplate* key_template =
      NewRsaSsaPssKeyTemplate(HashType::SHA256, HashType::SHA256, 32, 3072,
                              RSA_F4)
          .release();
  return *key_template;
}

// static
const KeyTemplate& SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4() {
  static const KeyTemplate* key_template =
      NewRsaSsaPssKeyTemplate(HashType::SHA512, HashType::SHA512, 64, 4096,
                              RSA_F4)
          .release();
  return *key_template;
}

// static
const google::crypto::tink::KeyTemplate& SignatureKeyTemplates::Ed25519() {
  static KeyTemplate* key_template = new KeyTemplate();
  key_template->set_type_url(
      absl::StrCat(kTypeGoogleapisCom, Ed25519PrivateKey().GetTypeName()));
  key_template->set_output_prefix_type(OutputPrefixType::TINK);
  return *key_template;
}

}  // namespace tink
}  // namespace crypto
