// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/webcrypto/algorithms/rsa.h"

#include <string_view>
#include <utility>

#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "components/webcrypto/algorithms/asymmetric_key_util.h"
#include "components/webcrypto/algorithms/util.h"
#include "components/webcrypto/blink_key_handle.h"
#include "components/webcrypto/generate_key_result.h"
#include "components/webcrypto/jwk.h"
#include "components/webcrypto/status.h"
#include "crypto/evp.h"
#include "crypto/keypair.h"
#include "crypto/openssl_util.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
#include "third_party/boringssl/src/include/openssl/bn.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/rsa.h"

namespace webcrypto {

namespace {

// Describes the RSA components for a parsed key. The names of the properties
// correspond with those from the JWK spec. Note that Chromium's WebCrypto
// implementation does not support multi-primes, so there is no parsed field
// for "oth".
struct JwkRsaInfo {
  bool is_private_key = false;
  std::vector<uint8_t> n;
  std::vector<uint8_t> e;
  std::vector<uint8_t> d;
  std::vector<uint8_t> p;
  std::vector<uint8_t> q;
  std::vector<uint8_t> dp;
  std::vector<uint8_t> dq;
  std::vector<uint8_t> qi;
};

// Parses a UTF-8 encoded JWK (key_data), and extracts the RSA components to
// |*result|. Returns Status::Success() on success, otherwise an error.
// In order for this to succeed:
//   * expected_alg must match the JWK's "alg", if present.
//   * expected_extractable must be consistent with the JWK's "ext", if
//     present.
//   * expected_usages must be a subset of the JWK's "key_ops" if present.
Status ReadRsaKeyJwk(base::span<const uint8_t> key_data,
                     std::string_view expected_alg,
                     bool expected_extractable,
                     blink::WebCryptoKeyUsageMask expected_usages,
                     JwkRsaInfo* result) {
  JwkReader jwk;
  Status status = jwk.Init(key_data, expected_extractable, expected_usages,
                           "RSA", expected_alg);
  if (status.IsError())
    return status;

  // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
  // in the JWK, while an RSA private key must have those, plus at least a "d"
  // (private exponent) entry.
  // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
  // section 6.3.
  status = jwk.GetBigInteger("n", &result->n);
  if (status.IsError())
    return status;
  status = jwk.GetBigInteger("e", &result->e);
  if (status.IsError())
    return status;

  result->is_private_key = jwk.HasMember("d");
  if (!result->is_private_key)
    return Status::Success();

  status = jwk.GetBigInteger("d", &result->d);
  if (status.IsError())
    return status;

  // The "p", "q", "dp", "dq", and "qi" properties are optional in the JWA
  // spec. However they are required by Chromium's WebCrypto implementation.

  status = jwk.GetBigInteger("p", &result->p);
  if (status.IsError())
    return status;

  status = jwk.GetBigInteger("q", &result->q);
  if (status.IsError())
    return status;

  status = jwk.GetBigInteger("dp", &result->dp);
  if (status.IsError())
    return status;

  status = jwk.GetBigInteger("dq", &result->dq);
  if (status.IsError())
    return status;

  status = jwk.GetBigInteger("qi", &result->qi);
  if (status.IsError())
    return status;

  return Status::Success();
}

// Converts a BIGNUM to a big endian byte array.
std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) {
  std::vector<uint8_t> v(BN_num_bytes(n));
  BN_bn2bin(n, v.data());
  return v;
}

// Creates a blink::WebCryptoAlgorithm having the modulus length and public
// exponent  of |key|.
Status CreateRsaHashedKeyAlgorithm(
    blink::WebCryptoAlgorithmId rsa_algorithm,
    blink::WebCryptoAlgorithmId hash_algorithm,
    EVP_PKEY* key,
    blink::WebCryptoKeyAlgorithm* key_algorithm) {
  DCHECK_EQ(EVP_PKEY_RSA, EVP_PKEY_id(key));

  RSA* rsa = EVP_PKEY_get0_RSA(key);
  if (!rsa)
    return Status::ErrorUnexpected();

  unsigned int modulus_length_bits = RSA_bits(rsa);

  // Convert the public exponent to big-endian representation.
  std::vector<uint8_t> e = BIGNUMToVector(RSA_get0_e(rsa));
  if (e.empty()) {
    return Status::ErrorUnexpected();
  }

  *key_algorithm = blink::WebCryptoKeyAlgorithm::CreateRsaHashed(
      rsa_algorithm, modulus_length_bits, e, hash_algorithm);

  return Status::Success();
}

// Creates a WebCryptoKey that wraps |private_key|.
Status CreateWebCryptoRsaPrivateKey(
    bssl::UniquePtr<EVP_PKEY> private_key,
    const blink::WebCryptoAlgorithmId rsa_algorithm_id,
    const blink::WebCryptoAlgorithm& hash,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    blink::WebCryptoKey* key) {
  blink::WebCryptoKeyAlgorithm key_algorithm;
  Status status = CreateRsaHashedKeyAlgorithm(
      rsa_algorithm_id, hash.Id(), private_key.get(), &key_algorithm);
  if (status.IsError())
    return status;

  return CreateWebCryptoPrivateKey(std::move(private_key), key_algorithm,
                                   extractable, usages, key);
}

// Creates a WebCryptoKey that wraps |public_key|.
Status CreateWebCryptoRsaPublicKey(
    bssl::UniquePtr<EVP_PKEY> public_key,
    const blink::WebCryptoAlgorithmId rsa_algorithm_id,
    const blink::WebCryptoAlgorithm& hash,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    blink::WebCryptoKey* key) {
  blink::WebCryptoKeyAlgorithm key_algorithm;
  Status status = CreateRsaHashedKeyAlgorithm(rsa_algorithm_id, hash.Id(),
                                              public_key.get(), &key_algorithm);
  if (status.IsError())
    return status;

  return CreateWebCryptoPublicKey(std::move(public_key), key_algorithm,
                                  extractable, usages, key);
}

Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
                           bool extractable,
                           blink::WebCryptoKeyUsageMask usages,
                           const JwkRsaInfo& params,
                           blink::WebCryptoKey* key) {
  bssl::UniquePtr<BIGNUM> n(
      BN_bin2bn(params.n.data(), params.n.size(), nullptr));
  bssl::UniquePtr<BIGNUM> e(
      BN_bin2bn(params.e.data(), params.e.size(), nullptr));
  bssl::UniquePtr<BIGNUM> d(
      BN_bin2bn(params.d.data(), params.d.size(), nullptr));
  bssl::UniquePtr<BIGNUM> p(
      BN_bin2bn(params.p.data(), params.p.size(), nullptr));
  bssl::UniquePtr<BIGNUM> q(
      BN_bin2bn(params.q.data(), params.q.size(), nullptr));
  bssl::UniquePtr<BIGNUM> dmp1(
      BN_bin2bn(params.dp.data(), params.dp.size(), nullptr));
  bssl::UniquePtr<BIGNUM> dmq1(
      BN_bin2bn(params.dq.data(), params.dq.size(), nullptr));
  bssl::UniquePtr<BIGNUM> iqmp(
      BN_bin2bn(params.qi.data(), params.qi.size(), nullptr));
  if (!n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp) {
    return Status::OperationError();
  }

  bssl::UniquePtr<RSA> rsa(RSA_new_private_key(n.get(), e.get(), d.get(),
                                               p.get(), q.get(), dmp1.get(),
                                               dmq1.get(), iqmp.get()));
  if (!rsa) {
    return Status::DataError();
  }

  // Create a corresponding EVP_PKEY.
  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
  if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
    return Status::OperationError();

  return CreateWebCryptoRsaPrivateKey(
      std::move(pkey), algorithm.Id(),
      algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
}

Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
                          bool extractable,
                          blink::WebCryptoKeyUsageMask usages,
                          base::span<const uint8_t> n,
                          base::span<const uint8_t> e,
                          blink::WebCryptoKey* key) {
  auto pubkey = crypto::keypair::PublicKey::FromRsaPublicKeyComponents(n, e);
  if (!pubkey) {
    return Status::OperationError();
  }

  return CreateWebCryptoRsaPublicKey(
      bssl::UpRef(pubkey->key()), algorithm.Id(),
      algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
}

// Synthesizes an import algorithm given a key algorithm, so that
// deserialization can re-use the ImportKey*() methods.
blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone(
    const blink::WebCryptoKeyAlgorithm& algorithm) {
  return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
      algorithm.Id(), new blink::WebCryptoRsaHashedImportParams(
                          algorithm.RsaHashedParams()->GetHash()));
}

}  // namespace

Status RsaHashedAlgorithm::GenerateKey(
    const blink::WebCryptoAlgorithm& algorithm,
    bool extractable,
    blink::WebCryptoKeyUsageMask combined_usages,
    GenerateKeyResult* result) const {
  blink::WebCryptoKeyUsageMask public_usages = 0;
  blink::WebCryptoKeyUsageMask private_usages = 0;

  Status status = GetUsagesForGenerateAsymmetricKey(
      combined_usages, all_public_key_usages_, all_private_key_usages_,
      &public_usages, &private_usages);
  if (status.IsError())
    return status;

  const blink::WebCryptoRsaHashedKeyGenParams* params =
      algorithm.RsaHashedKeyGenParams();

  unsigned int modulus_length_bits = params->ModulusLengthBits();

  // Limit the RSA key sizes to:
  //   * Multiple of 8 bits
  //   * 256 bits to 8K bits
  //
  // These correspond with limitations at the time there was an NSS WebCrypto
  // implementation. However in practice the upper bound is also helpful
  // because generating large RSA keys is very slow. In particular, generating
  // keys > 8192 bits takes multiple minutes of compute time without providing
  // any increase in realistic security level.
  if (modulus_length_bits < 256 || modulus_length_bits > 8192 ||
      (modulus_length_bits % 8) != 0) {
    return Status::ErrorGenerateRsaUnsupportedModulus();
  }

  std::optional<uint32_t> public_exponent = params->PublicExponentAsU32();
  if (!public_exponent) {
    return Status::ErrorGenerateKeyPublicExponent();
  }

  // The canonical RSA exponent is 65537, but 3 is also common. Use an allowlist
  // because RSA key generation is a probabilistic process and may hang on
  // invalid exponents.
  if (*public_exponent != 3 && *public_exponent != 65537) {
    return Status::ErrorGenerateKeyPublicExponent();
  }

  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);

  // Generate an RSA key pair.
  bssl::UniquePtr<RSA> rsa_private_key(RSA_new());
  bssl::UniquePtr<BIGNUM> bn(BN_new());
  if (!rsa_private_key.get() || !bn.get() ||
      !BN_set_word(bn.get(), *public_exponent)) {
    return Status::OperationError();
  }

  if (!RSA_generate_key_ex(rsa_private_key.get(), modulus_length_bits, bn.get(),
                           nullptr)) {
    return Status::OperationError();
  }

  // Construct an EVP_PKEY for the private key.
  bssl::UniquePtr<EVP_PKEY> private_pkey(EVP_PKEY_new());
  if (!private_pkey ||
      !EVP_PKEY_set1_RSA(private_pkey.get(), rsa_private_key.get())) {
    return Status::OperationError();
  }

  // Construct an EVP_PKEY for the public key.
  bssl::UniquePtr<RSA> rsa_public_key(RSAPublicKey_dup(rsa_private_key.get()));
  bssl::UniquePtr<EVP_PKEY> public_pkey(EVP_PKEY_new());
  if (!public_pkey ||
      !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) {
    return Status::OperationError();
  }

  blink::WebCryptoKey public_key;
  blink::WebCryptoKey private_key;

  // Note that extractable is unconditionally set to true. This is because per
  // the WebCrypto spec generated public keys are always extractable.
  status = CreateWebCryptoRsaPublicKey(std::move(public_pkey), algorithm.Id(),
                                       params->GetHash(), true, public_usages,
                                       &public_key);
  if (status.IsError())
    return status;

  status = CreateWebCryptoRsaPrivateKey(std::move(private_pkey), algorithm.Id(),
                                        params->GetHash(), extractable,
                                        private_usages, &private_key);
  if (status.IsError())
    return status;

  result->AssignKeyPair(public_key, private_key);
  return Status::Success();
}

Status RsaHashedAlgorithm::ImportKey(blink::WebCryptoKeyFormat format,
                                     base::span<const uint8_t> key_data,
                                     const blink::WebCryptoAlgorithm& algorithm,
                                     bool extractable,
                                     blink::WebCryptoKeyUsageMask usages,
                                     blink::WebCryptoKey* key) const {
  switch (format) {
    case blink::kWebCryptoKeyFormatPkcs8:
      return ImportKeyPkcs8(key_data, algorithm, extractable, usages, key);
    case blink::kWebCryptoKeyFormatSpki:
      return ImportKeySpki(key_data, algorithm, extractable, usages, key);
    case blink::kWebCryptoKeyFormatJwk:
      return ImportKeyJwk(key_data, algorithm, extractable, usages, key);
    default:
      return Status::ErrorUnsupportedImportKeyFormat();
  }
}

Status RsaHashedAlgorithm::ExportKey(blink::WebCryptoKeyFormat format,
                                     const blink::WebCryptoKey& key,
                                     std::vector<uint8_t>* buffer) const {
  switch (format) {
    case blink::kWebCryptoKeyFormatPkcs8:
      return ExportKeyPkcs8(key, buffer);
    case blink::kWebCryptoKeyFormatSpki:
      return ExportKeySpki(key, buffer);
    case blink::kWebCryptoKeyFormatJwk:
      return ExportKeyJwk(key, buffer);
    default:
      return Status::ErrorUnsupportedExportKeyFormat();
  }
}

Status RsaHashedAlgorithm::ImportKeyPkcs8(
    base::span<const uint8_t> key_data,
    const blink::WebCryptoAlgorithm& algorithm,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    blink::WebCryptoKey* key) const {
  Status status = CheckKeyCreationUsages(all_private_key_usages_, usages);
  if (status.IsError())
    return status;

  bssl::UniquePtr<EVP_PKEY> private_key;
  status = ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_RSA, &private_key);
  if (status.IsError())
    return status;

  // Verify the parameters of the key.
  RSA* rsa = EVP_PKEY_get0_RSA(private_key.get());
  if (!rsa)
    return Status::ErrorUnexpected();
  if (!RSA_check_key(rsa))
    return Status::DataError();

  // TODO(eroman): Validate the algorithm OID against the webcrypto provided
  // hash. http://crbug.com/389400

  return CreateWebCryptoRsaPrivateKey(
      std::move(private_key), algorithm.Id(),
      algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
}

Status RsaHashedAlgorithm::ImportKeySpki(
    base::span<const uint8_t> key_data,
    const blink::WebCryptoAlgorithm& algorithm,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    blink::WebCryptoKey* key) const {
  Status status = CheckKeyCreationUsages(all_public_key_usages_, usages);
  if (status.IsError())
    return status;

  bssl::UniquePtr<EVP_PKEY> public_key;
  status = ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_RSA, &public_key);
  if (status.IsError())
    return status;

  // TODO(eroman): Validate the algorithm OID against the webcrypto provided
  // hash. http://crbug.com/389400

  return CreateWebCryptoRsaPublicKey(
      std::move(public_key), algorithm.Id(),
      algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
}

Status RsaHashedAlgorithm::ImportKeyJwk(
    base::span<const uint8_t> key_data,
    const blink::WebCryptoAlgorithm& algorithm,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    blink::WebCryptoKey* key) const {
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);

  const char* jwk_algorithm =
      GetJwkAlgorithm(algorithm.RsaHashedImportParams()->GetHash().Id());

  if (!jwk_algorithm)
    return Status::ErrorUnexpected();

  JwkRsaInfo jwk;
  Status status =
      ReadRsaKeyJwk(key_data, jwk_algorithm, extractable, usages, &jwk);
  if (status.IsError())
    return status;

  // Once the key type is known, verify the usages.
  if (jwk.is_private_key) {
    status = CheckKeyCreationUsages(all_private_key_usages_, usages);
  } else {
    status = CheckKeyCreationUsages(all_public_key_usages_, usages);
  }

  if (status.IsError())
    return status;

  return jwk.is_private_key
             ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key)
             : ImportRsaPublicKey(algorithm, extractable, usages, jwk.n, jwk.e,
                                  key);
}

Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key,
                                          std::vector<uint8_t>* buffer) const {
  if (key.GetType() != blink::kWebCryptoKeyTypePrivate)
    return Status::ErrorUnexpectedKeyType();
  *buffer = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key));
  return Status::Success();
}

Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key,
                                         std::vector<uint8_t>* buffer) const {
  if (key.GetType() != blink::kWebCryptoKeyTypePublic)
    return Status::ErrorUnexpectedKeyType();
  *buffer = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key));
  return Status::Success();
}

Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
                                        std::vector<uint8_t>* buffer) const {
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);

  EVP_PKEY* pkey = GetEVP_PKEY(key);
  RSA* rsa = EVP_PKEY_get0_RSA(pkey);
  if (!rsa)
    return Status::ErrorUnexpected();

  const char* jwk_algorithm =
      GetJwkAlgorithm(key.Algorithm().RsaHashedParams()->GetHash().Id());
  if (!jwk_algorithm)
    return Status::ErrorUnexpected();

  switch (key.GetType()) {
    case blink::kWebCryptoKeyTypePublic: {
      JwkWriter writer(jwk_algorithm, key.Extractable(), key.Usages(), "RSA");
      writer.SetBytes("n", BIGNUMToVector(RSA_get0_n(rsa)));
      writer.SetBytes("e", BIGNUMToVector(RSA_get0_e(rsa)));
      writer.ToJson(buffer);
      return Status::Success();
    }
    case blink::kWebCryptoKeyTypePrivate: {
      JwkWriter writer(jwk_algorithm, key.Extractable(), key.Usages(), "RSA");
      writer.SetBytes("n", BIGNUMToVector(RSA_get0_n(rsa)));
      writer.SetBytes("e", BIGNUMToVector(RSA_get0_e(rsa)));
      writer.SetBytes("d", BIGNUMToVector(RSA_get0_d(rsa)));
      // Although these are "optional" in the JWA, WebCrypto spec requires them
      // to be emitted.
      writer.SetBytes("p", BIGNUMToVector(RSA_get0_p(rsa)));
      writer.SetBytes("q", BIGNUMToVector(RSA_get0_q(rsa)));
      writer.SetBytes("dp", BIGNUMToVector(RSA_get0_dmp1(rsa)));
      writer.SetBytes("dq", BIGNUMToVector(RSA_get0_dmq1(rsa)));
      writer.SetBytes("qi", BIGNUMToVector(RSA_get0_iqmp(rsa)));
      writer.ToJson(buffer);
      return Status::Success();
    }

    default:
      return Status::ErrorUnexpected();
  }
}

// TODO(eroman): Defer import to the crypto thread. http://crbug.com/430763
Status RsaHashedAlgorithm::DeserializeKeyForClone(
    const blink::WebCryptoKeyAlgorithm& algorithm,
    blink::WebCryptoKeyType type,
    bool extractable,
    blink::WebCryptoKeyUsageMask usages,
    base::span<const uint8_t> key_data,
    blink::WebCryptoKey* key) const {
  if (algorithm.ParamsType() !=
      blink::kWebCryptoKeyAlgorithmParamsTypeRsaHashed)
    return Status::ErrorUnexpected();

  blink::WebCryptoAlgorithm import_algorithm =
      SynthesizeImportAlgorithmForClone(algorithm);

  Status status;

  // The serialized data will be either SPKI or PKCS8 formatted.
  switch (type) {
    case blink::kWebCryptoKeyTypePublic:
      status =
          ImportKeySpki(key_data, import_algorithm, extractable, usages, key);
      break;
    case blink::kWebCryptoKeyTypePrivate:
      status =
          ImportKeyPkcs8(key_data, import_algorithm, extractable, usages, key);
      break;
    default:
      return Status::ErrorUnexpected();
  }

  if (!status.IsSuccess())
    return status;

  // There is some duplicated information in the serialized format used by
  // structured clone (since the KeyAlgorithm is serialized separately from the
  // key data). Use this extra information to further validate what was
  // deserialized from the key data.

  if (algorithm.Id() != key->Algorithm().Id())
    return Status::ErrorUnexpected();

  if (key->GetType() != type)
    return Status::ErrorUnexpected();

  if (algorithm.RsaHashedParams()->ModulusLengthBits() !=
      key->Algorithm().RsaHashedParams()->ModulusLengthBits()) {
    return Status::ErrorUnexpected();
  }

  if (algorithm.RsaHashedParams()->PublicExponent().size() !=
          key->Algorithm().RsaHashedParams()->PublicExponent().size() ||
      0 != UNSAFE_TODO(memcmp(
               algorithm.RsaHashedParams()->PublicExponent().data(),
               key->Algorithm().RsaHashedParams()->PublicExponent().data(),
               key->Algorithm().RsaHashedParams()->PublicExponent().size()))) {
    return Status::ErrorUnexpected();
  }

  return Status::Success();
}

}  // namespace webcrypto
