11cb0ef41Sopenharmony_ci#include "crypto/crypto_sig.h"
21cb0ef41Sopenharmony_ci#include "async_wrap-inl.h"
31cb0ef41Sopenharmony_ci#include "base_object-inl.h"
41cb0ef41Sopenharmony_ci#include "crypto/crypto_ec.h"
51cb0ef41Sopenharmony_ci#include "crypto/crypto_keys.h"
61cb0ef41Sopenharmony_ci#include "crypto/crypto_util.h"
71cb0ef41Sopenharmony_ci#include "env-inl.h"
81cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
91cb0ef41Sopenharmony_ci#include "threadpoolwork-inl.h"
101cb0ef41Sopenharmony_ci#include "v8.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace node {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciusing v8::ArrayBuffer;
151cb0ef41Sopenharmony_ciusing v8::BackingStore;
161cb0ef41Sopenharmony_ciusing v8::Boolean;
171cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
181cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
191cb0ef41Sopenharmony_ciusing v8::HandleScope;
201cb0ef41Sopenharmony_ciusing v8::Int32;
211cb0ef41Sopenharmony_ciusing v8::Isolate;
221cb0ef41Sopenharmony_ciusing v8::Just;
231cb0ef41Sopenharmony_ciusing v8::Local;
241cb0ef41Sopenharmony_ciusing v8::Maybe;
251cb0ef41Sopenharmony_ciusing v8::Nothing;
261cb0ef41Sopenharmony_ciusing v8::Object;
271cb0ef41Sopenharmony_ciusing v8::Uint32;
281cb0ef41Sopenharmony_ciusing v8::Value;
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_cinamespace crypto {
311cb0ef41Sopenharmony_cinamespace {
321cb0ef41Sopenharmony_cibool ValidateDSAParameters(EVP_PKEY* key) {
331cb0ef41Sopenharmony_ci  /* Validate DSA2 parameters from FIPS 186-4 */
341cb0ef41Sopenharmony_ci#if OPENSSL_VERSION_MAJOR >= 3
351cb0ef41Sopenharmony_ci  if (EVP_default_properties_is_fips_enabled(nullptr) &&
361cb0ef41Sopenharmony_ci      EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
371cb0ef41Sopenharmony_ci#else
381cb0ef41Sopenharmony_ci  if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
391cb0ef41Sopenharmony_ci#endif
401cb0ef41Sopenharmony_ci    const DSA* dsa = EVP_PKEY_get0_DSA(key);
411cb0ef41Sopenharmony_ci    const BIGNUM* p;
421cb0ef41Sopenharmony_ci    DSA_get0_pqg(dsa, &p, nullptr, nullptr);
431cb0ef41Sopenharmony_ci    size_t L = BN_num_bits(p);
441cb0ef41Sopenharmony_ci    const BIGNUM* q;
451cb0ef41Sopenharmony_ci    DSA_get0_pqg(dsa, nullptr, &q, nullptr);
461cb0ef41Sopenharmony_ci    size_t N = BN_num_bits(q);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci    return (L == 1024 && N == 160) ||
491cb0ef41Sopenharmony_ci           (L == 2048 && N == 224) ||
501cb0ef41Sopenharmony_ci           (L == 2048 && N == 256) ||
511cb0ef41Sopenharmony_ci           (L == 3072 && N == 256);
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  return true;
551cb0ef41Sopenharmony_ci}
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_cibool ApplyRSAOptions(const ManagedEVPPKey& pkey,
581cb0ef41Sopenharmony_ci                     EVP_PKEY_CTX* pkctx,
591cb0ef41Sopenharmony_ci                     int padding,
601cb0ef41Sopenharmony_ci                     const Maybe<int>& salt_len) {
611cb0ef41Sopenharmony_ci  if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA ||
621cb0ef41Sopenharmony_ci      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 ||
631cb0ef41Sopenharmony_ci      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) {
641cb0ef41Sopenharmony_ci    if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0)
651cb0ef41Sopenharmony_ci      return false;
661cb0ef41Sopenharmony_ci    if (padding == RSA_PKCS1_PSS_PADDING && salt_len.IsJust()) {
671cb0ef41Sopenharmony_ci      if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.FromJust()) <= 0)
681cb0ef41Sopenharmony_ci        return false;
691cb0ef41Sopenharmony_ci    }
701cb0ef41Sopenharmony_ci  }
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  return true;
731cb0ef41Sopenharmony_ci}
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_cistd::unique_ptr<BackingStore> Node_SignFinal(Environment* env,
761cb0ef41Sopenharmony_ci                                             EVPMDPointer&& mdctx,
771cb0ef41Sopenharmony_ci                                             const ManagedEVPPKey& pkey,
781cb0ef41Sopenharmony_ci                                             int padding,
791cb0ef41Sopenharmony_ci                                             Maybe<int> pss_salt_len) {
801cb0ef41Sopenharmony_ci  unsigned char m[EVP_MAX_MD_SIZE];
811cb0ef41Sopenharmony_ci  unsigned int m_len;
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
841cb0ef41Sopenharmony_ci    return nullptr;
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  int signed_sig_len = EVP_PKEY_size(pkey.get());
871cb0ef41Sopenharmony_ci  CHECK_GE(signed_sig_len, 0);
881cb0ef41Sopenharmony_ci  size_t sig_len = static_cast<size_t>(signed_sig_len);
891cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> sig;
901cb0ef41Sopenharmony_ci  {
911cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
921cb0ef41Sopenharmony_ci    sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len);
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
951cb0ef41Sopenharmony_ci  if (pkctx &&
961cb0ef41Sopenharmony_ci      EVP_PKEY_sign_init(pkctx.get()) &&
971cb0ef41Sopenharmony_ci      ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
981cb0ef41Sopenharmony_ci      EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) &&
991cb0ef41Sopenharmony_ci      EVP_PKEY_sign(pkctx.get(), static_cast<unsigned char*>(sig->Data()),
1001cb0ef41Sopenharmony_ci                    &sig_len, m, m_len)) {
1011cb0ef41Sopenharmony_ci    CHECK_LE(sig_len, sig->ByteLength());
1021cb0ef41Sopenharmony_ci    if (sig_len == 0)
1031cb0ef41Sopenharmony_ci      sig = ArrayBuffer::NewBackingStore(env->isolate(), 0);
1041cb0ef41Sopenharmony_ci    else
1051cb0ef41Sopenharmony_ci      sig = BackingStore::Reallocate(env->isolate(), std::move(sig), sig_len);
1061cb0ef41Sopenharmony_ci    return sig;
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  return nullptr;
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciint GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
1131cb0ef41Sopenharmony_ci  return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING :
1141cb0ef41Sopenharmony_ci                                                         RSA_PKCS1_PADDING;
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ciunsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
1181cb0ef41Sopenharmony_ci  int bits, base_id = EVP_PKEY_base_id(pkey.get());
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  if (base_id == EVP_PKEY_DSA) {
1211cb0ef41Sopenharmony_ci    const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
1221cb0ef41Sopenharmony_ci    // Both r and s are computed mod q, so their width is limited by that of q.
1231cb0ef41Sopenharmony_ci    bits = BN_num_bits(DSA_get0_q(dsa_key));
1241cb0ef41Sopenharmony_ci  } else if (base_id == EVP_PKEY_EC) {
1251cb0ef41Sopenharmony_ci    const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
1261cb0ef41Sopenharmony_ci    const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
1271cb0ef41Sopenharmony_ci    bits = EC_GROUP_order_bits(ec_group);
1281cb0ef41Sopenharmony_ci  } else {
1291cb0ef41Sopenharmony_ci    return kNoDsaSignature;
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  return (bits + 7) / 8;
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cibool ExtractP1363(
1361cb0ef41Sopenharmony_ci    const unsigned char* sig_data,
1371cb0ef41Sopenharmony_ci    unsigned char* out,
1381cb0ef41Sopenharmony_ci    size_t len,
1391cb0ef41Sopenharmony_ci    size_t n) {
1401cb0ef41Sopenharmony_ci  ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, len));
1411cb0ef41Sopenharmony_ci  if (!asn1_sig)
1421cb0ef41Sopenharmony_ci    return false;
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  const BIGNUM* pr = ECDSA_SIG_get0_r(asn1_sig.get());
1451cb0ef41Sopenharmony_ci  const BIGNUM* ps = ECDSA_SIG_get0_s(asn1_sig.get());
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  return BN_bn2binpad(pr, out, n) > 0 && BN_bn2binpad(ps, out + n, n) > 0;
1481cb0ef41Sopenharmony_ci}
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci// Returns the maximum size of each of the integers (r, s) of the DSA signature.
1511cb0ef41Sopenharmony_cistd::unique_ptr<BackingStore> ConvertSignatureToP1363(Environment* env,
1521cb0ef41Sopenharmony_ci    const ManagedEVPPKey& pkey, std::unique_ptr<BackingStore>&& signature) {
1531cb0ef41Sopenharmony_ci  unsigned int n = GetBytesOfRS(pkey);
1541cb0ef41Sopenharmony_ci  if (n == kNoDsaSignature)
1551cb0ef41Sopenharmony_ci    return std::move(signature);
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> buf;
1581cb0ef41Sopenharmony_ci  {
1591cb0ef41Sopenharmony_ci    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
1601cb0ef41Sopenharmony_ci    buf = ArrayBuffer::NewBackingStore(env->isolate(), 2 * n);
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci  if (!ExtractP1363(static_cast<unsigned char*>(signature->Data()),
1631cb0ef41Sopenharmony_ci                    static_cast<unsigned char*>(buf->Data()),
1641cb0ef41Sopenharmony_ci                    signature->ByteLength(), n))
1651cb0ef41Sopenharmony_ci    return std::move(signature);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  return buf;
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci// Returns the maximum size of each of the integers (r, s) of the DSA signature.
1711cb0ef41Sopenharmony_ciByteSource ConvertSignatureToP1363(
1721cb0ef41Sopenharmony_ci    Environment* env,
1731cb0ef41Sopenharmony_ci    const ManagedEVPPKey& pkey,
1741cb0ef41Sopenharmony_ci    const ByteSource& signature) {
1751cb0ef41Sopenharmony_ci  unsigned int n = GetBytesOfRS(pkey);
1761cb0ef41Sopenharmony_ci  if (n == kNoDsaSignature)
1771cb0ef41Sopenharmony_ci    return ByteSource();
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  const unsigned char* sig_data = signature.data<unsigned char>();
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  ByteSource::Builder out(n * 2);
1821cb0ef41Sopenharmony_ci  memset(out.data<void>(), 0, n * 2);
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  if (!ExtractP1363(sig_data, out.data<unsigned char>(), signature.size(), n))
1851cb0ef41Sopenharmony_ci    return ByteSource();
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  return std::move(out).release();
1881cb0ef41Sopenharmony_ci}
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ciByteSource ConvertSignatureToDER(
1911cb0ef41Sopenharmony_ci      const ManagedEVPPKey& pkey,
1921cb0ef41Sopenharmony_ci      ByteSource&& out) {
1931cb0ef41Sopenharmony_ci  unsigned int n = GetBytesOfRS(pkey);
1941cb0ef41Sopenharmony_ci  if (n == kNoDsaSignature)
1951cb0ef41Sopenharmony_ci    return std::move(out);
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  const unsigned char* sig_data = out.data<unsigned char>();
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  if (out.size() != 2 * n)
2001cb0ef41Sopenharmony_ci    return ByteSource();
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  ECDSASigPointer asn1_sig(ECDSA_SIG_new());
2031cb0ef41Sopenharmony_ci  CHECK(asn1_sig);
2041cb0ef41Sopenharmony_ci  BIGNUM* r = BN_new();
2051cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(r);
2061cb0ef41Sopenharmony_ci  BIGNUM* s = BN_new();
2071cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(s);
2081cb0ef41Sopenharmony_ci  CHECK_EQ(r, BN_bin2bn(sig_data, n, r));
2091cb0ef41Sopenharmony_ci  CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s));
2101cb0ef41Sopenharmony_ci  CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s));
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci  unsigned char* data = nullptr;
2131cb0ef41Sopenharmony_ci  int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  if (len <= 0)
2161cb0ef41Sopenharmony_ci    return ByteSource();
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  CHECK_NOT_NULL(data);
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  return ByteSource::Allocated(data, len);
2211cb0ef41Sopenharmony_ci}
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_civoid CheckThrow(Environment* env, SignBase::Error error) {
2241cb0ef41Sopenharmony_ci  HandleScope scope(env->isolate());
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  switch (error) {
2271cb0ef41Sopenharmony_ci    case SignBase::Error::kSignUnknownDigest:
2281cb0ef41Sopenharmony_ci      return THROW_ERR_CRYPTO_INVALID_DIGEST(env);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci    case SignBase::Error::kSignNotInitialised:
2311cb0ef41Sopenharmony_ci      return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised");
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci    case SignBase::Error::kSignMalformedSignature:
2341cb0ef41Sopenharmony_ci      return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature");
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci    case SignBase::Error::kSignInit:
2371cb0ef41Sopenharmony_ci    case SignBase::Error::kSignUpdate:
2381cb0ef41Sopenharmony_ci    case SignBase::Error::kSignPrivateKey:
2391cb0ef41Sopenharmony_ci    case SignBase::Error::kSignPublicKey:
2401cb0ef41Sopenharmony_ci      {
2411cb0ef41Sopenharmony_ci        unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
2421cb0ef41Sopenharmony_ci        if (err)
2431cb0ef41Sopenharmony_ci          return ThrowCryptoError(env, err);
2441cb0ef41Sopenharmony_ci        switch (error) {
2451cb0ef41Sopenharmony_ci          case SignBase::Error::kSignInit:
2461cb0ef41Sopenharmony_ci            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
2471cb0ef41Sopenharmony_ci                "EVP_SignInit_ex failed");
2481cb0ef41Sopenharmony_ci          case SignBase::Error::kSignUpdate:
2491cb0ef41Sopenharmony_ci            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
2501cb0ef41Sopenharmony_ci                "EVP_SignUpdate failed");
2511cb0ef41Sopenharmony_ci          case SignBase::Error::kSignPrivateKey:
2521cb0ef41Sopenharmony_ci            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
2531cb0ef41Sopenharmony_ci                "PEM_read_bio_PrivateKey failed");
2541cb0ef41Sopenharmony_ci          case SignBase::Error::kSignPublicKey:
2551cb0ef41Sopenharmony_ci            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
2561cb0ef41Sopenharmony_ci                "PEM_read_bio_PUBKEY failed");
2571cb0ef41Sopenharmony_ci          default:
2581cb0ef41Sopenharmony_ci            ABORT();
2591cb0ef41Sopenharmony_ci        }
2601cb0ef41Sopenharmony_ci      }
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci    case SignBase::Error::kSignOk:
2631cb0ef41Sopenharmony_ci      return;
2641cb0ef41Sopenharmony_ci  }
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_cibool IsOneShot(const ManagedEVPPKey& key) {
2681cb0ef41Sopenharmony_ci  switch (EVP_PKEY_id(key.get())) {
2691cb0ef41Sopenharmony_ci    case EVP_PKEY_ED25519:
2701cb0ef41Sopenharmony_ci    case EVP_PKEY_ED448:
2711cb0ef41Sopenharmony_ci      return true;
2721cb0ef41Sopenharmony_ci    default:
2731cb0ef41Sopenharmony_ci      return false;
2741cb0ef41Sopenharmony_ci  }
2751cb0ef41Sopenharmony_ci}
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_cibool UseP1363Encoding(const ManagedEVPPKey& key,
2781cb0ef41Sopenharmony_ci                      const DSASigEnc& dsa_encoding) {
2791cb0ef41Sopenharmony_ci  switch (EVP_PKEY_id(key.get())) {
2801cb0ef41Sopenharmony_ci    case EVP_PKEY_EC:
2811cb0ef41Sopenharmony_ci    case EVP_PKEY_DSA:
2821cb0ef41Sopenharmony_ci      return dsa_encoding == kSigEncP1363;
2831cb0ef41Sopenharmony_ci    default:
2841cb0ef41Sopenharmony_ci      return false;
2851cb0ef41Sopenharmony_ci  }
2861cb0ef41Sopenharmony_ci}
2871cb0ef41Sopenharmony_ci}  // namespace
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ciSignBase::Error SignBase::Init(const char* sign_type) {
2901cb0ef41Sopenharmony_ci  CHECK_NULL(mdctx_);
2911cb0ef41Sopenharmony_ci  // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
2921cb0ef41Sopenharmony_ci  // exposed through the public API.
2931cb0ef41Sopenharmony_ci  if (strcmp(sign_type, "dss1") == 0 ||
2941cb0ef41Sopenharmony_ci      strcmp(sign_type, "DSS1") == 0) {
2951cb0ef41Sopenharmony_ci    sign_type = "SHA1";
2961cb0ef41Sopenharmony_ci  }
2971cb0ef41Sopenharmony_ci  const EVP_MD* md = EVP_get_digestbyname(sign_type);
2981cb0ef41Sopenharmony_ci  if (md == nullptr)
2991cb0ef41Sopenharmony_ci    return kSignUnknownDigest;
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  mdctx_.reset(EVP_MD_CTX_new());
3021cb0ef41Sopenharmony_ci  if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) {
3031cb0ef41Sopenharmony_ci    mdctx_.reset();
3041cb0ef41Sopenharmony_ci    return kSignInit;
3051cb0ef41Sopenharmony_ci  }
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  return kSignOk;
3081cb0ef41Sopenharmony_ci}
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ciSignBase::Error SignBase::Update(const char* data, size_t len) {
3111cb0ef41Sopenharmony_ci  if (mdctx_ == nullptr)
3121cb0ef41Sopenharmony_ci    return kSignNotInitialised;
3131cb0ef41Sopenharmony_ci  if (!EVP_DigestUpdate(mdctx_.get(), data, len))
3141cb0ef41Sopenharmony_ci    return kSignUpdate;
3151cb0ef41Sopenharmony_ci  return kSignOk;
3161cb0ef41Sopenharmony_ci}
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ciSignBase::SignBase(Environment* env, Local<Object> wrap)
3191cb0ef41Sopenharmony_ci    : BaseObject(env, wrap) {}
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_civoid SignBase::MemoryInfo(MemoryTracker* tracker) const {
3221cb0ef41Sopenharmony_ci  tracker->TrackFieldWithSize("mdctx", mdctx_ ? kSizeOf_EVP_MD_CTX : 0);
3231cb0ef41Sopenharmony_ci}
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ciSign::Sign(Environment* env, Local<Object> wrap) : SignBase(env, wrap) {
3261cb0ef41Sopenharmony_ci  MakeWeak();
3271cb0ef41Sopenharmony_ci}
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_civoid Sign::Initialize(Environment* env, Local<Object> target) {
3301cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
3311cb0ef41Sopenharmony_ci  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  t->InstanceTemplate()->SetInternalFieldCount(
3341cb0ef41Sopenharmony_ci      SignBase::kInternalFieldCount);
3351cb0ef41Sopenharmony_ci  t->Inherit(BaseObject::GetConstructorTemplate(env));
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "init", SignInit);
3381cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "update", SignUpdate);
3391cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "sign", SignFinal);
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  SetConstructorFunction(env->context(), target, "Sign", t);
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  SignJob::Initialize(env, target);
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci  constexpr int kSignJobModeSign = SignConfiguration::kSign;
3461cb0ef41Sopenharmony_ci  constexpr int kSignJobModeVerify = SignConfiguration::kVerify;
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, kSignJobModeSign);
3491cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, kSignJobModeVerify);
3501cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, kSigEncDER);
3511cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
3521cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING);
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_civoid Sign::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
3561cb0ef41Sopenharmony_ci  registry->Register(New);
3571cb0ef41Sopenharmony_ci  registry->Register(SignInit);
3581cb0ef41Sopenharmony_ci  registry->Register(SignUpdate);
3591cb0ef41Sopenharmony_ci  registry->Register(SignFinal);
3601cb0ef41Sopenharmony_ci  SignJob::RegisterExternalReferences(registry);
3611cb0ef41Sopenharmony_ci}
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_civoid Sign::New(const FunctionCallbackInfo<Value>& args) {
3641cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
3651cb0ef41Sopenharmony_ci  new Sign(env, args.This());
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_civoid Sign::SignInit(const FunctionCallbackInfo<Value>& args) {
3691cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
3701cb0ef41Sopenharmony_ci  Sign* sign;
3711cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  const node::Utf8Value sign_type(args.GetIsolate(), args[0]);
3741cb0ef41Sopenharmony_ci  crypto::CheckThrow(env, sign->Init(*sign_type));
3751cb0ef41Sopenharmony_ci}
3761cb0ef41Sopenharmony_ci
3771cb0ef41Sopenharmony_civoid Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
3781cb0ef41Sopenharmony_ci  Decode<Sign>(args, [](Sign* sign, const FunctionCallbackInfo<Value>& args,
3791cb0ef41Sopenharmony_ci                        const char* data, size_t size) {
3801cb0ef41Sopenharmony_ci    Environment* env = Environment::GetCurrent(args);
3811cb0ef41Sopenharmony_ci    if (UNLIKELY(size > INT_MAX))
3821cb0ef41Sopenharmony_ci      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
3831cb0ef41Sopenharmony_ci    Error err = sign->Update(data, size);
3841cb0ef41Sopenharmony_ci    crypto::CheckThrow(sign->env(), err);
3851cb0ef41Sopenharmony_ci  });
3861cb0ef41Sopenharmony_ci}
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ciSign::SignResult Sign::SignFinal(
3891cb0ef41Sopenharmony_ci    const ManagedEVPPKey& pkey,
3901cb0ef41Sopenharmony_ci    int padding,
3911cb0ef41Sopenharmony_ci    const Maybe<int>& salt_len,
3921cb0ef41Sopenharmony_ci    DSASigEnc dsa_sig_enc) {
3931cb0ef41Sopenharmony_ci  if (!mdctx_)
3941cb0ef41Sopenharmony_ci    return SignResult(kSignNotInitialised);
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  EVPMDPointer mdctx = std::move(mdctx_);
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  if (!ValidateDSAParameters(pkey.get()))
3991cb0ef41Sopenharmony_ci    return SignResult(kSignPrivateKey);
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_ci  std::unique_ptr<BackingStore> buffer =
4021cb0ef41Sopenharmony_ci      Node_SignFinal(env(), std::move(mdctx), pkey, padding, salt_len);
4031cb0ef41Sopenharmony_ci  Error error = buffer ? kSignOk : kSignPrivateKey;
4041cb0ef41Sopenharmony_ci  if (error == kSignOk && dsa_sig_enc == kSigEncP1363) {
4051cb0ef41Sopenharmony_ci    buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer));
4061cb0ef41Sopenharmony_ci    CHECK_NOT_NULL(buffer->Data());
4071cb0ef41Sopenharmony_ci  }
4081cb0ef41Sopenharmony_ci  return SignResult(error, std::move(buffer));
4091cb0ef41Sopenharmony_ci}
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_civoid Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
4121cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
4131cb0ef41Sopenharmony_ci  Sign* sign;
4141cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  ClearErrorOnReturn clear_error_on_return;
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  unsigned int offset = 0;
4191cb0ef41Sopenharmony_ci  ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true);
4201cb0ef41Sopenharmony_ci  if (!key)
4211cb0ef41Sopenharmony_ci    return;
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  int padding = GetDefaultSignPadding(key);
4241cb0ef41Sopenharmony_ci  if (!args[offset]->IsUndefined()) {
4251cb0ef41Sopenharmony_ci    CHECK(args[offset]->IsInt32());
4261cb0ef41Sopenharmony_ci    padding = args[offset].As<Int32>()->Value();
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  Maybe<int> salt_len = Nothing<int>();
4301cb0ef41Sopenharmony_ci  if (!args[offset + 1]->IsUndefined()) {
4311cb0ef41Sopenharmony_ci    CHECK(args[offset + 1]->IsInt32());
4321cb0ef41Sopenharmony_ci    salt_len = Just<int>(args[offset + 1].As<Int32>()->Value());
4331cb0ef41Sopenharmony_ci  }
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  CHECK(args[offset + 2]->IsInt32());
4361cb0ef41Sopenharmony_ci  DSASigEnc dsa_sig_enc =
4371cb0ef41Sopenharmony_ci      static_cast<DSASigEnc>(args[offset + 2].As<Int32>()->Value());
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci  SignResult ret = sign->SignFinal(
4401cb0ef41Sopenharmony_ci      key,
4411cb0ef41Sopenharmony_ci      padding,
4421cb0ef41Sopenharmony_ci      salt_len,
4431cb0ef41Sopenharmony_ci      dsa_sig_enc);
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci  if (ret.error != kSignOk)
4461cb0ef41Sopenharmony_ci    return crypto::CheckThrow(env, ret.error);
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  Local<ArrayBuffer> ab =
4491cb0ef41Sopenharmony_ci      ArrayBuffer::New(env->isolate(), std::move(ret.signature));
4501cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(
4511cb0ef41Sopenharmony_ci      Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>()));
4521cb0ef41Sopenharmony_ci}
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ciVerify::Verify(Environment* env, Local<Object> wrap)
4551cb0ef41Sopenharmony_ci  : SignBase(env, wrap) {
4561cb0ef41Sopenharmony_ci  MakeWeak();
4571cb0ef41Sopenharmony_ci}
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_civoid Verify::Initialize(Environment* env, Local<Object> target) {
4601cb0ef41Sopenharmony_ci  Isolate* isolate = env->isolate();
4611cb0ef41Sopenharmony_ci  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci  t->InstanceTemplate()->SetInternalFieldCount(
4641cb0ef41Sopenharmony_ci      SignBase::kInternalFieldCount);
4651cb0ef41Sopenharmony_ci  t->Inherit(BaseObject::GetConstructorTemplate(env));
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "init", VerifyInit);
4681cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "update", VerifyUpdate);
4691cb0ef41Sopenharmony_ci  SetProtoMethod(isolate, t, "verify", VerifyFinal);
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  SetConstructorFunction(env->context(), target, "Verify", t);
4721cb0ef41Sopenharmony_ci}
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_civoid Verify::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
4751cb0ef41Sopenharmony_ci  registry->Register(New);
4761cb0ef41Sopenharmony_ci  registry->Register(VerifyInit);
4771cb0ef41Sopenharmony_ci  registry->Register(VerifyUpdate);
4781cb0ef41Sopenharmony_ci  registry->Register(VerifyFinal);
4791cb0ef41Sopenharmony_ci}
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_civoid Verify::New(const FunctionCallbackInfo<Value>& args) {
4821cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
4831cb0ef41Sopenharmony_ci  new Verify(env, args.This());
4841cb0ef41Sopenharmony_ci}
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_civoid Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
4871cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
4881cb0ef41Sopenharmony_ci  Verify* verify;
4891cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  const node::Utf8Value verify_type(args.GetIsolate(), args[0]);
4921cb0ef41Sopenharmony_ci  crypto::CheckThrow(env, verify->Init(*verify_type));
4931cb0ef41Sopenharmony_ci}
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_civoid Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
4961cb0ef41Sopenharmony_ci  Decode<Verify>(args, [](Verify* verify,
4971cb0ef41Sopenharmony_ci                          const FunctionCallbackInfo<Value>& args,
4981cb0ef41Sopenharmony_ci                          const char* data, size_t size) {
4991cb0ef41Sopenharmony_ci    Environment* env = Environment::GetCurrent(args);
5001cb0ef41Sopenharmony_ci    if (UNLIKELY(size > INT_MAX))
5011cb0ef41Sopenharmony_ci      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
5021cb0ef41Sopenharmony_ci    Error err = verify->Update(data, size);
5031cb0ef41Sopenharmony_ci    crypto::CheckThrow(verify->env(), err);
5041cb0ef41Sopenharmony_ci  });
5051cb0ef41Sopenharmony_ci}
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ciSignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey,
5081cb0ef41Sopenharmony_ci                                    const ByteSource& sig,
5091cb0ef41Sopenharmony_ci                                    int padding,
5101cb0ef41Sopenharmony_ci                                    const Maybe<int>& saltlen,
5111cb0ef41Sopenharmony_ci                                    bool* verify_result) {
5121cb0ef41Sopenharmony_ci  if (!mdctx_)
5131cb0ef41Sopenharmony_ci    return kSignNotInitialised;
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  unsigned char m[EVP_MAX_MD_SIZE];
5161cb0ef41Sopenharmony_ci  unsigned int m_len;
5171cb0ef41Sopenharmony_ci  *verify_result = false;
5181cb0ef41Sopenharmony_ci  EVPMDPointer mdctx = std::move(mdctx_);
5191cb0ef41Sopenharmony_ci
5201cb0ef41Sopenharmony_ci  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
5211cb0ef41Sopenharmony_ci    return kSignPublicKey;
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
5241cb0ef41Sopenharmony_ci  if (pkctx &&
5251cb0ef41Sopenharmony_ci      EVP_PKEY_verify_init(pkctx.get()) > 0 &&
5261cb0ef41Sopenharmony_ci      ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
5271cb0ef41Sopenharmony_ci      EVP_PKEY_CTX_set_signature_md(pkctx.get(),
5281cb0ef41Sopenharmony_ci                                    EVP_MD_CTX_md(mdctx.get())) > 0) {
5291cb0ef41Sopenharmony_ci    const unsigned char* s = sig.data<unsigned char>();
5301cb0ef41Sopenharmony_ci    const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
5311cb0ef41Sopenharmony_ci    *verify_result = r == 1;
5321cb0ef41Sopenharmony_ci  }
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  return kSignOk;
5351cb0ef41Sopenharmony_ci}
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_civoid Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
5381cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
5391cb0ef41Sopenharmony_ci  ClearErrorOnReturn clear_error_on_return;
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci  Verify* verify;
5421cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_ci  unsigned int offset = 0;
5451cb0ef41Sopenharmony_ci  ManagedEVPPKey pkey =
5461cb0ef41Sopenharmony_ci      ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
5471cb0ef41Sopenharmony_ci  if (!pkey)
5481cb0ef41Sopenharmony_ci    return;
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  ArrayBufferOrViewContents<char> hbuf(args[offset]);
5511cb0ef41Sopenharmony_ci  if (UNLIKELY(!hbuf.CheckSizeInt32()))
5521cb0ef41Sopenharmony_ci    return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  int padding = GetDefaultSignPadding(pkey);
5551cb0ef41Sopenharmony_ci  if (!args[offset + 1]->IsUndefined()) {
5561cb0ef41Sopenharmony_ci    CHECK(args[offset + 1]->IsInt32());
5571cb0ef41Sopenharmony_ci    padding = args[offset + 1].As<Int32>()->Value();
5581cb0ef41Sopenharmony_ci  }
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci  Maybe<int> salt_len = Nothing<int>();
5611cb0ef41Sopenharmony_ci  if (!args[offset + 2]->IsUndefined()) {
5621cb0ef41Sopenharmony_ci    CHECK(args[offset + 2]->IsInt32());
5631cb0ef41Sopenharmony_ci    salt_len = Just<int>(args[offset + 2].As<Int32>()->Value());
5641cb0ef41Sopenharmony_ci  }
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  CHECK(args[offset + 3]->IsInt32());
5671cb0ef41Sopenharmony_ci  DSASigEnc dsa_sig_enc =
5681cb0ef41Sopenharmony_ci      static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value());
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci  ByteSource signature = hbuf.ToByteSource();
5711cb0ef41Sopenharmony_ci  if (dsa_sig_enc == kSigEncP1363) {
5721cb0ef41Sopenharmony_ci    signature = ConvertSignatureToDER(pkey, hbuf.ToByteSource());
5731cb0ef41Sopenharmony_ci    if (signature.data() == nullptr)
5741cb0ef41Sopenharmony_ci      return crypto::CheckThrow(env, Error::kSignMalformedSignature);
5751cb0ef41Sopenharmony_ci  }
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci  bool verify_result;
5781cb0ef41Sopenharmony_ci  Error err = verify->VerifyFinal(pkey, signature, padding,
5791cb0ef41Sopenharmony_ci                                  salt_len, &verify_result);
5801cb0ef41Sopenharmony_ci  if (err != kSignOk)
5811cb0ef41Sopenharmony_ci    return crypto::CheckThrow(env, err);
5821cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(verify_result);
5831cb0ef41Sopenharmony_ci}
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ciSignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
5861cb0ef41Sopenharmony_ci    : job_mode(other.job_mode),
5871cb0ef41Sopenharmony_ci      mode(other.mode),
5881cb0ef41Sopenharmony_ci      key(std::move(other.key)),
5891cb0ef41Sopenharmony_ci      data(std::move(other.data)),
5901cb0ef41Sopenharmony_ci      signature(std::move(other.signature)),
5911cb0ef41Sopenharmony_ci      digest(other.digest),
5921cb0ef41Sopenharmony_ci      flags(other.flags),
5931cb0ef41Sopenharmony_ci      padding(other.padding),
5941cb0ef41Sopenharmony_ci      salt_length(other.salt_length),
5951cb0ef41Sopenharmony_ci      dsa_encoding(other.dsa_encoding) {}
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ciSignConfiguration& SignConfiguration::operator=(
5981cb0ef41Sopenharmony_ci    SignConfiguration&& other) noexcept {
5991cb0ef41Sopenharmony_ci  if (&other == this) return *this;
6001cb0ef41Sopenharmony_ci  this->~SignConfiguration();
6011cb0ef41Sopenharmony_ci  return *new (this) SignConfiguration(std::move(other));
6021cb0ef41Sopenharmony_ci}
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_civoid SignConfiguration::MemoryInfo(MemoryTracker* tracker) const {
6051cb0ef41Sopenharmony_ci  tracker->TrackField("key", key);
6061cb0ef41Sopenharmony_ci  if (job_mode == kCryptoJobAsync) {
6071cb0ef41Sopenharmony_ci    tracker->TrackFieldWithSize("data", data.size());
6081cb0ef41Sopenharmony_ci    tracker->TrackFieldWithSize("signature", signature.size());
6091cb0ef41Sopenharmony_ci  }
6101cb0ef41Sopenharmony_ci}
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ciMaybe<bool> SignTraits::AdditionalConfig(
6131cb0ef41Sopenharmony_ci    CryptoJobMode mode,
6141cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args,
6151cb0ef41Sopenharmony_ci    unsigned int offset,
6161cb0ef41Sopenharmony_ci    SignConfiguration* params) {
6171cb0ef41Sopenharmony_ci  ClearErrorOnReturn clear_error_on_return;
6181cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci  params->job_mode = mode;
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  CHECK(args[offset]->IsUint32());  // Sign Mode
6231cb0ef41Sopenharmony_ci
6241cb0ef41Sopenharmony_ci  params->mode =
6251cb0ef41Sopenharmony_ci      static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value());
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  ManagedEVPPKey key;
6281cb0ef41Sopenharmony_ci  unsigned int keyParamOffset = offset + 1;
6291cb0ef41Sopenharmony_ci  if (params->mode == SignConfiguration::kVerify) {
6301cb0ef41Sopenharmony_ci    key = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &keyParamOffset);
6311cb0ef41Sopenharmony_ci  } else {
6321cb0ef41Sopenharmony_ci    key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &keyParamOffset, true);
6331cb0ef41Sopenharmony_ci  }
6341cb0ef41Sopenharmony_ci  if (!key)
6351cb0ef41Sopenharmony_ci    return Nothing<bool>();
6361cb0ef41Sopenharmony_ci  params->key = key;
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  ArrayBufferOrViewContents<char> data(args[offset + 5]);
6391cb0ef41Sopenharmony_ci  if (UNLIKELY(!data.CheckSizeInt32())) {
6401cb0ef41Sopenharmony_ci    THROW_ERR_OUT_OF_RANGE(env, "data is too big");
6411cb0ef41Sopenharmony_ci    return Nothing<bool>();
6421cb0ef41Sopenharmony_ci  }
6431cb0ef41Sopenharmony_ci  params->data = mode == kCryptoJobAsync
6441cb0ef41Sopenharmony_ci      ? data.ToCopy()
6451cb0ef41Sopenharmony_ci      : data.ToByteSource();
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci  if (args[offset + 6]->IsString()) {
6481cb0ef41Sopenharmony_ci    Utf8Value digest(env->isolate(), args[offset + 6]);
6491cb0ef41Sopenharmony_ci    params->digest = EVP_get_digestbyname(*digest);
6501cb0ef41Sopenharmony_ci    if (params->digest == nullptr) {
6511cb0ef41Sopenharmony_ci      THROW_ERR_CRYPTO_INVALID_DIGEST(env, "Invalid digest: %s", *digest);
6521cb0ef41Sopenharmony_ci      return Nothing<bool>();
6531cb0ef41Sopenharmony_ci    }
6541cb0ef41Sopenharmony_ci  }
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  if (args[offset + 7]->IsInt32()) {  // Salt length
6571cb0ef41Sopenharmony_ci    params->flags |= SignConfiguration::kHasSaltLength;
6581cb0ef41Sopenharmony_ci    params->salt_length = args[offset + 7].As<Int32>()->Value();
6591cb0ef41Sopenharmony_ci  }
6601cb0ef41Sopenharmony_ci  if (args[offset + 8]->IsUint32()) {  // Padding
6611cb0ef41Sopenharmony_ci    params->flags |= SignConfiguration::kHasPadding;
6621cb0ef41Sopenharmony_ci    params->padding = args[offset + 8].As<Uint32>()->Value();
6631cb0ef41Sopenharmony_ci  }
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci  if (args[offset + 9]->IsUint32()) {  // DSA Encoding
6661cb0ef41Sopenharmony_ci    params->dsa_encoding =
6671cb0ef41Sopenharmony_ci        static_cast<DSASigEnc>(args[offset + 9].As<Uint32>()->Value());
6681cb0ef41Sopenharmony_ci    if (params->dsa_encoding != kSigEncDER &&
6691cb0ef41Sopenharmony_ci        params->dsa_encoding != kSigEncP1363) {
6701cb0ef41Sopenharmony_ci      THROW_ERR_OUT_OF_RANGE(env, "invalid signature encoding");
6711cb0ef41Sopenharmony_ci      return Nothing<bool>();
6721cb0ef41Sopenharmony_ci    }
6731cb0ef41Sopenharmony_ci  }
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  if (params->mode == SignConfiguration::kVerify) {
6761cb0ef41Sopenharmony_ci    ArrayBufferOrViewContents<char> signature(args[offset + 10]);
6771cb0ef41Sopenharmony_ci    if (UNLIKELY(!signature.CheckSizeInt32())) {
6781cb0ef41Sopenharmony_ci      THROW_ERR_OUT_OF_RANGE(env, "signature is too big");
6791cb0ef41Sopenharmony_ci      return Nothing<bool>();
6801cb0ef41Sopenharmony_ci    }
6811cb0ef41Sopenharmony_ci    // If this is an EC key (assuming ECDSA) we need to convert the
6821cb0ef41Sopenharmony_ci    // the signature from WebCrypto format into DER format...
6831cb0ef41Sopenharmony_ci    ManagedEVPPKey m_pkey = params->key;
6841cb0ef41Sopenharmony_ci    Mutex::ScopedLock lock(*m_pkey.mutex());
6851cb0ef41Sopenharmony_ci    if (UseP1363Encoding(m_pkey, params->dsa_encoding)) {
6861cb0ef41Sopenharmony_ci      params->signature =
6871cb0ef41Sopenharmony_ci          ConvertSignatureToDER(m_pkey, signature.ToByteSource());
6881cb0ef41Sopenharmony_ci    } else {
6891cb0ef41Sopenharmony_ci      params->signature = mode == kCryptoJobAsync
6901cb0ef41Sopenharmony_ci          ? signature.ToCopy()
6911cb0ef41Sopenharmony_ci          : signature.ToByteSource();
6921cb0ef41Sopenharmony_ci    }
6931cb0ef41Sopenharmony_ci  }
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci  return Just(true);
6961cb0ef41Sopenharmony_ci}
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_cibool SignTraits::DeriveBits(
6991cb0ef41Sopenharmony_ci    Environment* env,
7001cb0ef41Sopenharmony_ci    const SignConfiguration& params,
7011cb0ef41Sopenharmony_ci    ByteSource* out) {
7021cb0ef41Sopenharmony_ci  ClearErrorOnReturn clear_error_on_return;
7031cb0ef41Sopenharmony_ci  EVPMDPointer context(EVP_MD_CTX_new());
7041cb0ef41Sopenharmony_ci  EVP_PKEY_CTX* ctx = nullptr;
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  switch (params.mode) {
7071cb0ef41Sopenharmony_ci    case SignConfiguration::kSign:
7081cb0ef41Sopenharmony_ci      if (!EVP_DigestSignInit(
7091cb0ef41Sopenharmony_ci              context.get(),
7101cb0ef41Sopenharmony_ci              &ctx,
7111cb0ef41Sopenharmony_ci              params.digest,
7121cb0ef41Sopenharmony_ci              nullptr,
7131cb0ef41Sopenharmony_ci              params.key.get())) {
7141cb0ef41Sopenharmony_ci        crypto::CheckThrow(env, SignBase::Error::kSignInit);
7151cb0ef41Sopenharmony_ci        return false;
7161cb0ef41Sopenharmony_ci      }
7171cb0ef41Sopenharmony_ci      break;
7181cb0ef41Sopenharmony_ci    case SignConfiguration::kVerify:
7191cb0ef41Sopenharmony_ci      if (!EVP_DigestVerifyInit(
7201cb0ef41Sopenharmony_ci              context.get(),
7211cb0ef41Sopenharmony_ci              &ctx,
7221cb0ef41Sopenharmony_ci              params.digest,
7231cb0ef41Sopenharmony_ci              nullptr,
7241cb0ef41Sopenharmony_ci              params.key.get())) {
7251cb0ef41Sopenharmony_ci        crypto::CheckThrow(env, SignBase::Error::kSignInit);
7261cb0ef41Sopenharmony_ci        return false;
7271cb0ef41Sopenharmony_ci      }
7281cb0ef41Sopenharmony_ci      break;
7291cb0ef41Sopenharmony_ci  }
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  int padding = params.flags & SignConfiguration::kHasPadding
7321cb0ef41Sopenharmony_ci      ? params.padding
7331cb0ef41Sopenharmony_ci      : GetDefaultSignPadding(params.key);
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength
7361cb0ef41Sopenharmony_ci      ? Just<int>(params.salt_length) : Nothing<int>();
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  if (!ApplyRSAOptions(
7391cb0ef41Sopenharmony_ci          params.key,
7401cb0ef41Sopenharmony_ci          ctx,
7411cb0ef41Sopenharmony_ci          padding,
7421cb0ef41Sopenharmony_ci          salt_length)) {
7431cb0ef41Sopenharmony_ci    crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
7441cb0ef41Sopenharmony_ci    return false;
7451cb0ef41Sopenharmony_ci  }
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci  switch (params.mode) {
7481cb0ef41Sopenharmony_ci    case SignConfiguration::kSign: {
7491cb0ef41Sopenharmony_ci      if (IsOneShot(params.key)) {
7501cb0ef41Sopenharmony_ci        size_t len;
7511cb0ef41Sopenharmony_ci        if (!EVP_DigestSign(
7521cb0ef41Sopenharmony_ci            context.get(),
7531cb0ef41Sopenharmony_ci            nullptr,
7541cb0ef41Sopenharmony_ci            &len,
7551cb0ef41Sopenharmony_ci            params.data.data<unsigned char>(),
7561cb0ef41Sopenharmony_ci            params.data.size())) {
7571cb0ef41Sopenharmony_ci          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
7581cb0ef41Sopenharmony_ci          return false;
7591cb0ef41Sopenharmony_ci        }
7601cb0ef41Sopenharmony_ci        ByteSource::Builder buf(len);
7611cb0ef41Sopenharmony_ci        if (!EVP_DigestSign(context.get(),
7621cb0ef41Sopenharmony_ci                            buf.data<unsigned char>(),
7631cb0ef41Sopenharmony_ci                            &len,
7641cb0ef41Sopenharmony_ci                            params.data.data<unsigned char>(),
7651cb0ef41Sopenharmony_ci                            params.data.size())) {
7661cb0ef41Sopenharmony_ci          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
7671cb0ef41Sopenharmony_ci          return false;
7681cb0ef41Sopenharmony_ci        }
7691cb0ef41Sopenharmony_ci        *out = std::move(buf).release(len);
7701cb0ef41Sopenharmony_ci      } else {
7711cb0ef41Sopenharmony_ci        size_t len;
7721cb0ef41Sopenharmony_ci        if (!EVP_DigestSignUpdate(
7731cb0ef41Sopenharmony_ci                context.get(),
7741cb0ef41Sopenharmony_ci                params.data.data<unsigned char>(),
7751cb0ef41Sopenharmony_ci                params.data.size()) ||
7761cb0ef41Sopenharmony_ci            !EVP_DigestSignFinal(context.get(), nullptr, &len)) {
7771cb0ef41Sopenharmony_ci          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
7781cb0ef41Sopenharmony_ci          return false;
7791cb0ef41Sopenharmony_ci        }
7801cb0ef41Sopenharmony_ci        ByteSource::Builder buf(len);
7811cb0ef41Sopenharmony_ci        if (!EVP_DigestSignFinal(
7821cb0ef41Sopenharmony_ci                context.get(), buf.data<unsigned char>(), &len)) {
7831cb0ef41Sopenharmony_ci          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
7841cb0ef41Sopenharmony_ci          return false;
7851cb0ef41Sopenharmony_ci        }
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci        if (UseP1363Encoding(params.key, params.dsa_encoding)) {
7881cb0ef41Sopenharmony_ci          *out = ConvertSignatureToP1363(
7891cb0ef41Sopenharmony_ci              env, params.key, std::move(buf).release());
7901cb0ef41Sopenharmony_ci        } else {
7911cb0ef41Sopenharmony_ci          *out = std::move(buf).release(len);
7921cb0ef41Sopenharmony_ci        }
7931cb0ef41Sopenharmony_ci      }
7941cb0ef41Sopenharmony_ci      break;
7951cb0ef41Sopenharmony_ci    }
7961cb0ef41Sopenharmony_ci    case SignConfiguration::kVerify: {
7971cb0ef41Sopenharmony_ci      ByteSource::Builder buf(1);
7981cb0ef41Sopenharmony_ci      buf.data<char>()[0] = 0;
7991cb0ef41Sopenharmony_ci      if (EVP_DigestVerify(
8001cb0ef41Sopenharmony_ci              context.get(),
8011cb0ef41Sopenharmony_ci              params.signature.data<unsigned char>(),
8021cb0ef41Sopenharmony_ci              params.signature.size(),
8031cb0ef41Sopenharmony_ci              params.data.data<unsigned char>(),
8041cb0ef41Sopenharmony_ci              params.data.size()) == 1) {
8051cb0ef41Sopenharmony_ci        buf.data<char>()[0] = 1;
8061cb0ef41Sopenharmony_ci      }
8071cb0ef41Sopenharmony_ci      *out = std::move(buf).release();
8081cb0ef41Sopenharmony_ci    }
8091cb0ef41Sopenharmony_ci  }
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_ci  return true;
8121cb0ef41Sopenharmony_ci}
8131cb0ef41Sopenharmony_ci
8141cb0ef41Sopenharmony_ciMaybe<bool> SignTraits::EncodeOutput(
8151cb0ef41Sopenharmony_ci    Environment* env,
8161cb0ef41Sopenharmony_ci    const SignConfiguration& params,
8171cb0ef41Sopenharmony_ci    ByteSource* out,
8181cb0ef41Sopenharmony_ci    Local<Value>* result) {
8191cb0ef41Sopenharmony_ci  switch (params.mode) {
8201cb0ef41Sopenharmony_ci    case SignConfiguration::kSign:
8211cb0ef41Sopenharmony_ci      *result = out->ToArrayBuffer(env);
8221cb0ef41Sopenharmony_ci      break;
8231cb0ef41Sopenharmony_ci    case SignConfiguration::kVerify:
8241cb0ef41Sopenharmony_ci      *result = Boolean::New(env->isolate(), out->data<char>()[0] == 1);
8251cb0ef41Sopenharmony_ci      break;
8261cb0ef41Sopenharmony_ci    default:
8271cb0ef41Sopenharmony_ci      UNREACHABLE();
8281cb0ef41Sopenharmony_ci  }
8291cb0ef41Sopenharmony_ci  return Just(!result->IsEmpty());
8301cb0ef41Sopenharmony_ci}
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci}  // namespace crypto
8331cb0ef41Sopenharmony_ci}  // namespace node
834