// Copyright 2021 Google LLC
//
// 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/internal/rsa_util.h"

#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "openssl/bn.h"
#include "tink/config/tink_fips.h"
#include "tink/internal/bn_util.h"
#include "tink/internal/err_util.h"
#include "tink/internal/ssl_unique_ptr.h"
#include "tink/internal/ssl_util.h"
#include "tink/util/errors.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"

namespace crypto {
namespace tink {
namespace internal {

constexpr int kMaxRsaModulusSizeBits = 16 * 1024;
// Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as
// the limit based on the recommendations in [1] and [2]. Windows CryptoAPI
// doesn't support values larger than 32 bits [3], so it is unlikely that
// exponents larger than 32 bits are being used for anything Windows commonly
// does.
//
// [1] https://www.imperialviolet.org/2012/03/16/rsae.html
// [2] https://www.imperialviolet.org/2012/03/17/rsados.html
// [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx
constexpr int kMaxRsaExponentBits = 33;

util::Status ValidateRsaModulusSize(size_t modulus_size) {
  if (modulus_size < 2048) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        absl::StrCat("Modulus size is ", modulus_size,
                     " only modulus size >= 2048-bit is supported"));
  }

  // In FIPS only mode we check here if the modulus is 2048- or 3072-bit, as
  // these are the only size which is covered by the FIPS validation and
  // supported by Tink. See
  // https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3318
  if (IsFipsModeEnabled()) {
    if (modulus_size != 2048 && modulus_size != 3072) {
      return util::Status(
          absl::StatusCode::kInternal,
          absl::StrCat("Modulus size is ", modulus_size,
                       " only modulus size 2048 or 3072 is supported."));
    }
  }

  return util::OkStatus();
}

util::Status ValidateRsaPublicExponent(const BIGNUM *exponent) {
  if (exponent == nullptr) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "Public exponent must not be NULL.");
  }

  if (BN_is_odd(exponent) == 0) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "Public exponent must be odd.");
  }

  if (CompareBignumWithWord(exponent, /*word=*/65536) <= 0) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "Public exponent must be greater than 65536.");
  }

  // OpenSSL doesn't pose a limit to the size of the exponent, so for
  // consistency w.r.t. BoringSSL, we enforce it here.
  if (BN_num_bits(exponent) > 32) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "Exponent size must be smaller than 32 bits");
  }
  return util::OkStatus();
}

util::Status ValidateRsaPublicExponent(absl::string_view exponent) {
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> e =
      internal::StringToBignum(exponent);
  if (!e.ok()) {
    return e.status();
  }
  return ValidateRsaPublicExponent(e->get());
}

util::Status NewRsaKeyPair(int modulus_size_in_bits, const BIGNUM *e,
                           RsaPrivateKey *private_key,
                           RsaPublicKey *public_key) {
  internal::SslUniquePtr<RSA> rsa(RSA_new());
  if (rsa == nullptr) {
    return util::Status(absl::StatusCode::kInternal,
                        "Could not initialize RSA.");
  }

  util::Status exponent_validation_res = ValidateRsaPublicExponent(e);
  if (!exponent_validation_res.ok()) {
    return exponent_validation_res;
  }

  internal::SslUniquePtr<BIGNUM> e_copy(BN_new());
  if (BN_copy(e_copy.get(), e) == nullptr) {
    return util::Status(absl::StatusCode::kInternal, internal::GetSslErrors());
  }
  if (RSA_generate_key_ex(rsa.get(), modulus_size_in_bits, e_copy.get(),
                          /*cb=*/nullptr) != 1) {
    return util::Status(absl::StatusCode::kInternal,
                        absl::StrCat("Error generating private key: ",
                                     internal::GetSslErrors()));
  }

  const BIGNUM *n_bn, *e_bn, *d_bn;
  RSA_get0_key(rsa.get(), &n_bn, &e_bn, &d_bn);

  // Save exponents.
  util::StatusOr<std::string> n_str =
      internal::BignumToString(n_bn, BN_num_bytes(n_bn));
  if (!n_str.ok()) {
    return n_str.status();
  }
  util::StatusOr<std::string> e_str =
      internal::BignumToString(e_bn, BN_num_bytes(e_bn));
  if (!e_str.ok()) {
    return e_str.status();
  }
  util::StatusOr<util::SecretData> d_str =
      internal::BignumToSecretData(d_bn, BN_num_bytes(d_bn));
  if (!d_str.ok()) {
    return d_str.status();
  }
  private_key->n = *std::move(n_str);
  private_key->e = *std::move(e_str);
  private_key->d = *std::move(d_str);
  public_key->n = private_key->n;
  public_key->e = private_key->e;

  // Save factors.
  const BIGNUM *p_bn, *q_bn;
  RSA_get0_factors(rsa.get(), &p_bn, &q_bn);
  util::StatusOr<util::SecretData> p_str =
      internal::BignumToSecretData(p_bn, BN_num_bytes(p_bn));
  if (!p_str.ok()) {
    return p_str.status();
  }
  util::StatusOr<util::SecretData> q_str =
      internal::BignumToSecretData(q_bn, BN_num_bytes(q_bn));
  if (!q_str.ok()) {
    return q_str.status();
  }
  private_key->p = *std::move(p_str);
  private_key->q = *std::move(q_str);

  // Save CRT parameters.
  const BIGNUM *dp_bn, *dq_bn, *crt_bn;
  RSA_get0_crt_params(rsa.get(), &dp_bn, &dq_bn, &crt_bn);
  util::StatusOr<util::SecretData> dp_str =
      internal::BignumToSecretData(dp_bn, BN_num_bytes(dp_bn));
  if (!dp_str.ok()) {
    return dp_str.status();
  }
  util::StatusOr<util::SecretData> dq_str =
      internal::BignumToSecretData(dq_bn, BN_num_bytes(dq_bn));
  if (!dq_str.ok()) {
    return dq_str.status();
  }
  util::StatusOr<util::SecretData> crt_str =
      internal::BignumToSecretData(crt_bn, BN_num_bytes(crt_bn));
  if (!crt_str.ok()) {
    return crt_str.status();
  }
  private_key->dp = *std::move(dp_str);
  private_key->dq = *std::move(dq_str);
  private_key->crt = *std::move(crt_str);

  return util::OkStatus();
}

util::Status GetRsaModAndExponents(const RsaPrivateKey &key, RSA *rsa) {
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> n =
      internal::StringToBignum(key.n);
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> e =
      internal::StringToBignum(key.e);
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> d =
      internal::StringToBignum(util::SecretDataAsStringView(key.d));
  if (!n.ok()) {
    return n.status();
  }
  if (!e.ok()) {
    return e.status();
  }
  if (!d.ok()) {
    return d.status();
  }
  if (RSA_set0_key(rsa, n->get(), e->get(), d->get()) != 1) {
    return util::Status(
        absl::StatusCode::kInternal,
        absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
  }
  // The RSA object takes ownership when RSA_set0_key is called.
  n->release();
  e->release();
  d->release();
  return util::OkStatus();
}

util::Status GetRsaPrimeFactors(const RsaPrivateKey &key, RSA *rsa) {
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> p =
      internal::StringToBignum(util::SecretDataAsStringView(key.p));
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> q =
      internal::StringToBignum(util::SecretDataAsStringView(key.q));
  if (!p.ok()) {
    return p.status();
  }
  if (!q.ok()) {
    return q.status();
  }
  if (RSA_set0_factors(rsa, p->get(), q->get()) != 1) {
    return util::Status(
        absl::StatusCode::kInternal,
        absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
  }
  p->release();
  q->release();
  return util::OkStatus();
}

util::Status GetRsaCrtParams(const RsaPrivateKey &key, RSA *rsa) {
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> dp =
      internal::StringToBignum(util::SecretDataAsStringView(key.dp));
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> dq =
      internal::StringToBignum(util::SecretDataAsStringView(key.dq));
  util::StatusOr<internal::SslUniquePtr<BIGNUM>> crt =
      internal::StringToBignum(util::SecretDataAsStringView(key.crt));
  if (!dp.ok()) {
    return dp.status();
  }
  if (!dq.ok()) {
    return dq.status();
  }
  if (!crt.ok()) {
    return crt.status();
  }
  if (RSA_set0_crt_params(rsa, dp->get(), dq->get(), crt->get()) != 1) {
    return util::Status(
        absl::StatusCode::kInternal,
        absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
  }
  dp->release();
  dq->release();
  crt->release();
  return util::OkStatus();
}

util::StatusOr<internal::SslUniquePtr<RSA>> RsaPrivateKeyToRsa(
    const RsaPrivateKey &private_key) {
  auto n = internal::StringToBignum(private_key.n);
  if (!n.ok()) {
    return n.status();
  }
  auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get()));
  if (!validation_result.ok()) {
    return validation_result;
  }
  // Check RSA's public exponent
  auto exponent_status = ValidateRsaPublicExponent(private_key.e);
  if (!exponent_status.ok()) {
    return exponent_status;
  }
  internal::SslUniquePtr<RSA> rsa(RSA_new());
  if (rsa.get() == nullptr) {
    return util::Status(absl::StatusCode::kInternal,
                        "BoringSsl RSA allocation error");
  }
  util::Status status = GetRsaModAndExponents(private_key, rsa.get());
  if (!status.ok()) {
    return status;
  }
  status = GetRsaPrimeFactors(private_key, rsa.get());
  if (!status.ok()) {
    return status;
  }
  status = GetRsaCrtParams(private_key, rsa.get());
  if (!status.ok()) {
    return status;
  }

  if (RSA_check_key(rsa.get()) == 0) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
  }
#ifdef OPENSSL_IS_BORINGSSL
  if (RSA_check_fips(rsa.get()) == 0) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        absl::StrCat("Could not load RSA key: ", internal::GetSslErrors()));
  }
#endif
  return std::move(rsa);
}

util::StatusOr<internal::SslUniquePtr<RSA>> RsaPublicKeyToRsa(
    const RsaPublicKey &public_key) {
  auto n = internal::StringToBignum(public_key.n);
  if (!n.ok()) {
    return n.status();
  }
  auto e = internal::StringToBignum(public_key.e);
  if (!e.ok()) {
    return e.status();
  }
  auto validation_result = ValidateRsaModulusSize(BN_num_bits(n->get()));
  if (!validation_result.ok()) {
    return validation_result;
  }
  internal::SslUniquePtr<RSA> rsa(RSA_new());
  if (rsa.get() == nullptr) {
    return util::Status(absl::StatusCode::kInternal, "RSA allocation error");
  }
  // The value d is null for a public RSA key.
  if (RSA_set0_key(rsa.get(), n->get(), e->get(),
                   /*d=*/nullptr) != 1) {
    return util::Status(absl::StatusCode::kInternal, "Could not set RSA key.");
  }
  n->release();
  e->release();
  return std::move(rsa);
}

util::Status RsaCheckPublicKey(const RSA *key) {
  if (key == nullptr) {
    return util::Status(absl::StatusCode::kInvalidArgument, "RSA key is null");
  }

  // BoringSSL `RSA_check_key` supports checking the public key.
  if (internal::IsBoringSsl()) {
    if (RSA_check_key(key) != 1) {
      return util::Status(absl::StatusCode::kInvalidArgument,
                          "Invalid RSA key format");
    }
    return util::OkStatus();
  }

  const BIGNUM *n = nullptr;
  const BIGNUM *e = nullptr;
  const BIGNUM *d = nullptr;
  RSA_get0_key(key, &n, &e, &d);

  if (e == nullptr) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "RSA key's public exponent is null");
  }
  if (n == nullptr) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "RSA key's public modulus is null");
  }

  // Check the size of the public modulus.
  unsigned n_bits = BN_num_bits(n);
  if (n_bits > kMaxRsaModulusSizeBits) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        absl::StrCat(
            "RSA key's public modulus size is too large; expected at most ",
            kMaxRsaModulusSizeBits, " bits, got ", n_bits));
  }

  unsigned e_bits = BN_num_bits(e);
  // Valis size is 1 < e_bits <= kMaxRsaExponentBits.
  if (e_bits > kMaxRsaExponentBits || e_bits < 2) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        absl::StrCat("Invalid public exponent size of ", e_bits, " bits"));
  }

  // The exponent must be odd to be relatively prime with phi(n).
  if (!BN_is_odd(e)) {
    return util::Status(absl::StatusCode::kInvalidArgument,
                        "Public exponent is not odd");
  }

  // Verify |n > e| first taking the shortcut of making sure the size in bits of
  // n is larger than the maximum modulus size; if this not the case, directly
  // compare n and e.
  if (n_bits <= kMaxRsaExponentBits || BN_ucmp(n, e) <= 0) {
    return util::Status(
        absl::StatusCode::kInvalidArgument,
        "RSA key's public exponent is smaller than the modulus");
  }
  return util::OkStatus();
}

}  // namespace internal
}  // namespace tink
}  // namespace crypto
