GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_sig.cc Lines: 392 482 81.3 %
Date: 2022-08-21 04:19:51 Branches: 206 344 59.9 %

Line Branch Exec Source
1
#include "crypto/crypto_sig.h"
2
#include "async_wrap-inl.h"
3
#include "base_object-inl.h"
4
#include "crypto/crypto_ec.h"
5
#include "crypto/crypto_keys.h"
6
#include "crypto/crypto_util.h"
7
#include "env-inl.h"
8
#include "memory_tracker-inl.h"
9
#include "threadpoolwork-inl.h"
10
#include "v8.h"
11
12
namespace node {
13
14
using v8::ArrayBuffer;
15
using v8::BackingStore;
16
using v8::FunctionCallbackInfo;
17
using v8::FunctionTemplate;
18
using v8::HandleScope;
19
using v8::Int32;
20
using v8::Isolate;
21
using v8::Just;
22
using v8::Local;
23
using v8::Maybe;
24
using v8::Nothing;
25
using v8::Object;
26
using v8::Uint32;
27
using v8::Value;
28
29
namespace crypto {
30
namespace {
31
112
bool ValidateDSAParameters(EVP_PKEY* key) {
32
  /* Validate DSA2 parameters from FIPS 186-4 */
33
#if OPENSSL_VERSION_MAJOR >= 3
34

112
  if (EVP_default_properties_is_fips_enabled(nullptr) &&
35
      EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
36
#else
37
  if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
38
#endif
39
    const DSA* dsa = EVP_PKEY_get0_DSA(key);
40
    const BIGNUM* p;
41
    DSA_get0_pqg(dsa, &p, nullptr, nullptr);
42
    size_t L = BN_num_bits(p);
43
    const BIGNUM* q;
44
    DSA_get0_pqg(dsa, nullptr, &q, nullptr);
45
    size_t N = BN_num_bits(q);
46
47
    return (L == 1024 && N == 160) ||
48
           (L == 2048 && N == 224) ||
49
           (L == 2048 && N == 256) ||
50
           (L == 3072 && N == 256);
51
  }
52
53
112
  return true;
54
}
55
56
2178
bool ApplyRSAOptions(const ManagedEVPPKey& pkey,
57
                     EVP_PKEY_CTX* pkctx,
58
                     int padding,
59
                     const Maybe<int>& salt_len) {
60
3097
  if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA ||
61

3097
      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 ||
62
919
      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) {
63
1592
    if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0)
64
3
      return false;
65

2911
    if (padding == RSA_PKCS1_PSS_PADDING && salt_len.IsJust()) {
66
1222
      if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.FromJust()) <= 0)
67
12
        return false;
68
    }
69
  }
70
71
2163
  return true;
72
}
73
74
112
std::unique_ptr<BackingStore> Node_SignFinal(Environment* env,
75
                                             EVPMDPointer&& mdctx,
76
                                             const ManagedEVPPKey& pkey,
77
                                             int padding,
78
                                             Maybe<int> pss_salt_len) {
79
  unsigned char m[EVP_MAX_MD_SIZE];
80
  unsigned int m_len;
81
82
112
  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
83
    return nullptr;
84
85
112
  int signed_sig_len = EVP_PKEY_size(pkey.get());
86
112
  CHECK_GE(signed_sig_len, 0);
87
112
  size_t sig_len = static_cast<size_t>(signed_sig_len);
88
112
  std::unique_ptr<BackingStore> sig;
89
  {
90
112
    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
91
112
    sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len);
92
  }
93
224
  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
94
112
  if (pkctx &&
95
336
      EVP_PKEY_sign_init(pkctx.get()) &&
96
216
      ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
97

328
      EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) &&
98
98
      EVP_PKEY_sign(pkctx.get(), static_cast<unsigned char*>(sig->Data()),
99
                    &sig_len, m, m_len)) {
100
97
    CHECK_LE(sig_len, sig->ByteLength());
101
97
    if (sig_len == 0)
102
      sig = ArrayBuffer::NewBackingStore(env->isolate(), 0);
103
    else
104
97
      sig = BackingStore::Reallocate(env->isolate(), std::move(sig), sig_len);
105
97
    return sig;
106
  }
107
108
15
  return nullptr;
109
}
110
111
1559
int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
112
1559
  return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING :
113
1559
                                                         RSA_PKCS1_PADDING;
114
}
115
116
290
unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
117
290
  int bits, base_id = EVP_PKEY_base_id(pkey.get());
118
119
290
  if (base_id == EVP_PKEY_DSA) {
120
28
    const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
121
    // Both r and s are computed mod q, so their width is limited by that of q.
122
28
    bits = BN_num_bits(DSA_get0_q(dsa_key));
123
262
  } else if (base_id == EVP_PKEY_EC) {
124
262
    const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
125
262
    const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
126
262
    bits = EC_GROUP_order_bits(ec_group);
127
  } else {
128
    return kNoDsaSignature;
129
  }
130
131
290
  return (bits + 7) / 8;
132
}
133
134
54
bool ExtractP1363(
135
    const unsigned char* sig_data,
136
    unsigned char* out,
137
    size_t len,
138
    size_t n) {
139
108
  ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, len));
140
54
  if (!asn1_sig)
141
    return false;
142
143
54
  const BIGNUM* pr = ECDSA_SIG_get0_r(asn1_sig.get());
144
54
  const BIGNUM* ps = ECDSA_SIG_get0_s(asn1_sig.get());
145
146

54
  return BN_bn2binpad(pr, out, n) > 0 && BN_bn2binpad(ps, out + n, n) > 0;
147
}
148
149
// Returns the maximum size of each of the integers (r, s) of the DSA signature.
150
std::unique_ptr<BackingStore> ConvertSignatureToP1363(Environment* env,
151
    const ManagedEVPPKey& pkey, std::unique_ptr<BackingStore>&& signature) {
152
  unsigned int n = GetBytesOfRS(pkey);
153
  if (n == kNoDsaSignature)
154
    return std::move(signature);
155
156
  std::unique_ptr<BackingStore> buf;
157
  {
158
    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
159
    buf = ArrayBuffer::NewBackingStore(env->isolate(), 2 * n);
160
  }
161
  if (!ExtractP1363(static_cast<unsigned char*>(signature->Data()),
162
                    static_cast<unsigned char*>(buf->Data()),
163
                    signature->ByteLength(), n))
164
    return std::move(signature);
165
166
  return buf;
167
}
168
169
// Returns the maximum size of each of the integers (r, s) of the DSA signature.
170
54
ByteSource ConvertSignatureToP1363(
171
    Environment* env,
172
    const ManagedEVPPKey& pkey,
173
    const ByteSource& signature) {
174
54
  unsigned int n = GetBytesOfRS(pkey);
175
54
  if (n == kNoDsaSignature)
176
    return ByteSource();
177
178
54
  const unsigned char* sig_data = signature.data<unsigned char>();
179
180
108
  ByteSource::Builder out(n * 2);
181
54
  memset(out.data<void>(), 0, n * 2);
182
183
54
  if (!ExtractP1363(sig_data, out.data<unsigned char>(), signature.size(), n))
184
    return ByteSource();
185
186
54
  return std::move(out).release();
187
}
188
189
236
ByteSource ConvertSignatureToDER(
190
      const ManagedEVPPKey& pkey,
191
      ByteSource&& out) {
192
236
  unsigned int n = GetBytesOfRS(pkey);
193
236
  if (n == kNoDsaSignature)
194
    return std::move(out);
195
196
236
  const unsigned char* sig_data = out.data<unsigned char>();
197
198
236
  if (out.size() != 2 * n)
199
46
    return ByteSource();
200
201
380
  ECDSASigPointer asn1_sig(ECDSA_SIG_new());
202
190
  CHECK(asn1_sig);
203
190
  BIGNUM* r = BN_new();
204
190
  CHECK_NOT_NULL(r);
205
190
  BIGNUM* s = BN_new();
206
190
  CHECK_NOT_NULL(s);
207
190
  CHECK_EQ(r, BN_bin2bn(sig_data, n, r));
208
190
  CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s));
209
190
  CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s));
210
211
190
  unsigned char* data = nullptr;
212
190
  int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);
213
214
190
  if (len <= 0)
215
    return ByteSource();
216
217
190
  CHECK_NOT_NULL(data);
218
219
190
  return ByteSource::Allocated(data, len);
220
}
221
222
1488
void CheckThrow(Environment* env, SignBase::Error error) {
223
1488
  HandleScope scope(env->isolate());
224
225

1488
  switch (error) {
226
1
    case SignBase::Error::kSignUnknownDigest:
227
1
      return THROW_ERR_CRYPTO_INVALID_DIGEST(env);
228
229
    case SignBase::Error::kSignNotInitialised:
230
      return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised");
231
232
    case SignBase::Error::kSignMalformedSignature:
233
      return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature");
234
235
29
    case SignBase::Error::kSignInit:
236
    case SignBase::Error::kSignUpdate:
237
    case SignBase::Error::kSignPrivateKey:
238
    case SignBase::Error::kSignPublicKey:
239
      {
240
29
        unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
241
29
        if (err)
242
29
          return ThrowCryptoError(env, err);
243
        switch (error) {
244
          case SignBase::Error::kSignInit:
245
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
246
                "EVP_SignInit_ex failed");
247
          case SignBase::Error::kSignUpdate:
248
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
249
                "EVP_SignUpdate failed");
250
          case SignBase::Error::kSignPrivateKey:
251
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
252
                "PEM_read_bio_PrivateKey failed");
253
          case SignBase::Error::kSignPublicKey:
254
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
255
                "PEM_read_bio_PUBKEY failed");
256
          default:
257
            ABORT();
258
        }
259
      }
260
261
1458
    case SignBase::Error::kSignOk:
262
1458
      return;
263
  }
264
}
265
266
278
bool IsOneShot(const ManagedEVPPKey& key) {
267
278
  switch (EVP_PKEY_id(key.get())) {
268
33
    case EVP_PKEY_ED25519:
269
    case EVP_PKEY_ED448:
270
33
      return true;
271
245
    default:
272
245
      return false;
273
  }
274
}
275
276
1439
bool UseP1363Encoding(const ManagedEVPPKey& key,
277
                      const DSASigEnc& dsa_encoding) {
278
1439
  switch (EVP_PKEY_id(key.get())) {
279
409
    case EVP_PKEY_EC:
280
    case EVP_PKEY_DSA:
281
409
      return dsa_encoding == kSigEncP1363;
282
1030
    default:
283
1030
      return false;
284
  }
285
}
286
}  // namespace
287
288
731
SignBase::Error SignBase::Init(const char* sign_type) {
289
731
  CHECK_NULL(mdctx_);
290
  // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
291
  // exposed through the public API.
292
731
  if (strcmp(sign_type, "dss1") == 0 ||
293
731
      strcmp(sign_type, "DSS1") == 0) {
294
2
    sign_type = "SHA1";
295
  }
296
731
  const EVP_MD* md = EVP_get_digestbyname(sign_type);
297
731
  if (md == nullptr)
298
1
    return kSignUnknownDigest;
299
300
730
  mdctx_.reset(EVP_MD_CTX_new());
301

730
  if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) {
302
    mdctx_.reset();
303
    return kSignInit;
304
  }
305
306
730
  return kSignOk;
307
}
308
309
728
SignBase::Error SignBase::Update(const char* data, size_t len) {
310
728
  if (mdctx_ == nullptr)
311
    return kSignNotInitialised;
312
728
  if (!EVP_DigestUpdate(mdctx_.get(), data, len))
313
    return kSignUpdate;
314
728
  return kSignOk;
315
}
316
317
731
SignBase::SignBase(Environment* env, Local<Object> wrap)
318
731
    : BaseObject(env, wrap) {}
319
320
void SignBase::MemoryInfo(MemoryTracker* tracker) const {
321
  tracker->TrackFieldWithSize("mdctx", mdctx_ ? kSizeOf_EVP_MD_CTX : 0);
322
}
323
324
138
Sign::Sign(Environment* env, Local<Object> wrap) : SignBase(env, wrap) {
325
138
  MakeWeak();
326
138
}
327
328
775
void Sign::Initialize(Environment* env, Local<Object> target) {
329
775
  Isolate* isolate = env->isolate();
330
775
  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
331
332
1550
  t->InstanceTemplate()->SetInternalFieldCount(
333
      SignBase::kInternalFieldCount);
334
775
  t->Inherit(BaseObject::GetConstructorTemplate(env));
335
336
775
  SetProtoMethod(isolate, t, "init", SignInit);
337
775
  SetProtoMethod(isolate, t, "update", SignUpdate);
338
775
  SetProtoMethod(isolate, t, "sign", SignFinal);
339
340
775
  SetConstructorFunction(env->context(), target, "Sign", t);
341
342
775
  SignJob::Initialize(env, target);
343
344
775
  constexpr int kSignJobModeSign = SignConfiguration::kSign;
345
775
  constexpr int kSignJobModeVerify = SignConfiguration::kVerify;
346
347
2325
  NODE_DEFINE_CONSTANT(target, kSignJobModeSign);
348
2325
  NODE_DEFINE_CONSTANT(target, kSignJobModeVerify);
349
2325
  NODE_DEFINE_CONSTANT(target, kSigEncDER);
350
2325
  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
351
1550
  NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING);
352
775
}
353
354
5357
void Sign::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
355
5357
  registry->Register(New);
356
5357
  registry->Register(SignInit);
357
5357
  registry->Register(SignUpdate);
358
5357
  registry->Register(SignFinal);
359
5357
  SignJob::RegisterExternalReferences(registry);
360
5357
}
361
362
138
void Sign::New(const FunctionCallbackInfo<Value>& args) {
363
138
  Environment* env = Environment::GetCurrent(args);
364
138
  new Sign(env, args.This());
365
138
}
366
367
138
void Sign::SignInit(const FunctionCallbackInfo<Value>& args) {
368
138
  Environment* env = Environment::GetCurrent(args);
369
  Sign* sign;
370
138
  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
371
372
276
  const node::Utf8Value sign_type(args.GetIsolate(), args[0]);
373
138
  crypto::CheckThrow(env, sign->Init(*sign_type));
374
}
375
376
125
void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
377
125
  Decode<Sign>(args, [](Sign* sign, const FunctionCallbackInfo<Value>& args,
378
125
                        const char* data, size_t size) {
379
125
    Environment* env = Environment::GetCurrent(args);
380
125
    if (UNLIKELY(size > INT_MAX))
381
      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
382
125
    Error err = sign->Update(data, size);
383
125
    crypto::CheckThrow(sign->env(), err);
384
  });
385
125
}
386
387
112
Sign::SignResult Sign::SignFinal(
388
    const ManagedEVPPKey& pkey,
389
    int padding,
390
    const Maybe<int>& salt_len,
391
    DSASigEnc dsa_sig_enc) {
392
112
  if (!mdctx_)
393
    return SignResult(kSignNotInitialised);
394
395
224
  EVPMDPointer mdctx = std::move(mdctx_);
396
397
112
  if (!ValidateDSAParameters(pkey.get()))
398
    return SignResult(kSignPrivateKey);
399
400
  std::unique_ptr<BackingStore> buffer =
401
224
      Node_SignFinal(env(), std::move(mdctx), pkey, padding, salt_len);
402
112
  Error error = buffer ? kSignOk : kSignPrivateKey;
403

112
  if (error == kSignOk && dsa_sig_enc == kSigEncP1363) {
404
    buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer));
405
    CHECK_NOT_NULL(buffer->Data());
406
  }
407
112
  return SignResult(error, std::move(buffer));
408
}
409
410
115
void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
411
115
  Environment* env = Environment::GetCurrent(args);
412
  Sign* sign;
413
133
  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
414
415
  ClearErrorOnReturn clear_error_on_return;
416
417
115
  unsigned int offset = 0;
418
115
  ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true);
419
115
  if (!key)
420
3
    return;
421
422
112
  int padding = GetDefaultSignPadding(key);
423

336
  if (!args[offset]->IsUndefined()) {
424

42
    CHECK(args[offset]->IsInt32());
425
63
    padding = args[offset].As<Int32>()->Value();
426
  }
427
428
112
  Maybe<int> salt_len = Nothing<int>();
429

336
  if (!args[offset + 1]->IsUndefined()) {
430

108
    CHECK(args[offset + 1]->IsInt32());
431
162
    salt_len = Just<int>(args[offset + 1].As<Int32>()->Value());
432
  }
433
434

224
  CHECK(args[offset + 2]->IsInt32());
435
  DSASigEnc dsa_sig_enc =
436
336
      static_cast<DSASigEnc>(args[offset + 2].As<Int32>()->Value());
437
438
  SignResult ret = sign->SignFinal(
439
      key,
440
      padding,
441
      salt_len,
442
112
      dsa_sig_enc);
443
444
112
  if (ret.error != kSignOk)
445
15
    return crypto::CheckThrow(env, ret.error);
446
447
  Local<ArrayBuffer> ab =
448
97
      ArrayBuffer::New(env->isolate(), std::move(ret.signature));
449
194
  args.GetReturnValue().Set(
450
194
      Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>()));
451
}
452
453
593
Verify::Verify(Environment* env, Local<Object> wrap)
454
593
  : SignBase(env, wrap) {
455
593
  MakeWeak();
456
593
}
457
458
775
void Verify::Initialize(Environment* env, Local<Object> target) {
459
775
  Isolate* isolate = env->isolate();
460
775
  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
461
462
1550
  t->InstanceTemplate()->SetInternalFieldCount(
463
      SignBase::kInternalFieldCount);
464
775
  t->Inherit(BaseObject::GetConstructorTemplate(env));
465
466
775
  SetProtoMethod(isolate, t, "init", VerifyInit);
467
775
  SetProtoMethod(isolate, t, "update", VerifyUpdate);
468
775
  SetProtoMethod(isolate, t, "verify", VerifyFinal);
469
470
775
  SetConstructorFunction(env->context(), target, "Verify", t);
471
775
}
472
473
5357
void Verify::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
474
5357
  registry->Register(New);
475
5357
  registry->Register(VerifyInit);
476
5357
  registry->Register(VerifyUpdate);
477
5357
  registry->Register(VerifyFinal);
478
5357
}
479
480
593
void Verify::New(const FunctionCallbackInfo<Value>& args) {
481
593
  Environment* env = Environment::GetCurrent(args);
482
593
  new Verify(env, args.This());
483
593
}
484
485
593
void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
486
593
  Environment* env = Environment::GetCurrent(args);
487
  Verify* verify;
488
593
  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
489
490
1186
  const node::Utf8Value verify_type(args.GetIsolate(), args[0]);
491
593
  crypto::CheckThrow(env, verify->Init(*verify_type));
492
}
493
494
603
void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
495
603
  Decode<Verify>(args, [](Verify* verify,
496
                          const FunctionCallbackInfo<Value>& args,
497
603
                          const char* data, size_t size) {
498
603
    Environment* env = Environment::GetCurrent(args);
499
603
    if (UNLIKELY(size > INT_MAX))
500
      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
501
603
    Error err = verify->Update(data, size);
502
603
    crypto::CheckThrow(verify->env(), err);
503
  });
504
603
}
505
506
586
SignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey,
507
                                    const ByteSource& sig,
508
                                    int padding,
509
                                    const Maybe<int>& saltlen,
510
                                    bool* verify_result) {
511
586
  if (!mdctx_)
512
    return kSignNotInitialised;
513
514
  unsigned char m[EVP_MAX_MD_SIZE];
515
  unsigned int m_len;
516
586
  *verify_result = false;
517
1172
  EVPMDPointer mdctx = std::move(mdctx_);
518
519
586
  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
520
    return kSignPublicKey;
521
522
586
  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
523
586
  if (pkctx &&
524
1758
      EVP_PKEY_verify_init(pkctx.get()) > 0 &&
525

1758
      ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
526
586
      EVP_PKEY_CTX_set_signature_md(pkctx.get(),
527
586
                                    EVP_MD_CTX_md(mdctx.get())) > 0) {
528
586
    const unsigned char* s = sig.data<unsigned char>();
529
586
    const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
530
586
    *verify_result = r == 1;
531
  }
532
533
586
  return kSignOk;
534
}
535
536
586
void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
537
586
  Environment* env = Environment::GetCurrent(args);
538
  ClearErrorOnReturn clear_error_on_return;
539
540
  Verify* verify;
541
586
  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
542
543
586
  unsigned int offset = 0;
544
  ManagedEVPPKey pkey =
545
586
      ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
546
586
  if (!pkey)
547
    return;
548
549
1172
  ArrayBufferOrViewContents<char> hbuf(args[offset]);
550
586
  if (UNLIKELY(!hbuf.CheckSizeInt32()))
551
    return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
552
553
586
  int padding = GetDefaultSignPadding(pkey);
554

1758
  if (!args[offset + 1]->IsUndefined()) {
555

744
    CHECK(args[offset + 1]->IsInt32());
556
1116
    padding = args[offset + 1].As<Int32>()->Value();
557
  }
558
559
586
  Maybe<int> salt_len = Nothing<int>();
560

1758
  if (!args[offset + 2]->IsUndefined()) {
561

924
    CHECK(args[offset + 2]->IsInt32());
562
1386
    salt_len = Just<int>(args[offset + 2].As<Int32>()->Value());
563
  }
564
565

1172
  CHECK(args[offset + 3]->IsInt32());
566
  DSASigEnc dsa_sig_enc =
567
1758
      static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value());
568
569
586
  ByteSource signature = hbuf.ToByteSource();
570
586
  if (dsa_sig_enc == kSigEncP1363) {
571
6
    signature = ConvertSignatureToDER(pkey, hbuf.ToByteSource());
572
6
    if (signature.data() == nullptr)
573
      return crypto::CheckThrow(env, Error::kSignMalformedSignature);
574
  }
575
576
  bool verify_result;
577
586
  Error err = verify->VerifyFinal(pkey, signature, padding,
578
                                  salt_len, &verify_result);
579
586
  if (err != kSignOk)
580
    return crypto::CheckThrow(env, err);
581
1172
  args.GetReturnValue().Set(verify_result);
582
}
583
584
1486
SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
585
1486
    : job_mode(other.job_mode),
586
1486
      mode(other.mode),
587
1486
      key(std::move(other.key)),
588
1486
      data(std::move(other.data)),
589
1486
      signature(std::move(other.signature)),
590
1486
      digest(other.digest),
591
1486
      flags(other.flags),
592
1486
      padding(other.padding),
593
1486
      salt_length(other.salt_length),
594
1486
      dsa_encoding(other.dsa_encoding) {}
595
596
SignConfiguration& SignConfiguration::operator=(
597
    SignConfiguration&& other) noexcept {
598
  if (&other == this) return *this;
599
  this->~SignConfiguration();
600
  return *new (this) SignConfiguration(std::move(other));
601
}
602
603
void SignConfiguration::MemoryInfo(MemoryTracker* tracker) const {
604
  tracker->TrackField("key", key);
605
  if (job_mode == kCryptoJobAsync) {
606
    tracker->TrackFieldWithSize("data", data.size());
607
    tracker->TrackFieldWithSize("signature", signature.size());
608
  }
609
}
610
611
1496
Maybe<bool> SignTraits::AdditionalConfig(
612
    CryptoJobMode mode,
613
    const FunctionCallbackInfo<Value>& args,
614
    unsigned int offset,
615
    SignConfiguration* params) {
616
1496
  ClearErrorOnReturn clear_error_on_return;
617
1496
  Environment* env = Environment::GetCurrent(args);
618
619
1496
  params->job_mode = mode;
620
621

2992
  CHECK(args[offset]->IsUint32());  // Sign Mode
622
623
1496
  params->mode =
624
4488
      static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value());
625
626
2992
  ManagedEVPPKey key;
627
1496
  unsigned int keyParamOffset = offset + 1;
628
1496
  if (params->mode == SignConfiguration::kVerify) {
629
1195
    key = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &keyParamOffset);
630
  } else {
631
301
    key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &keyParamOffset, true);
632
  }
633
1496
  if (!key)
634
9
    return Nothing<bool>();
635
1487
  params->key = key;
636
637
2974
  ArrayBufferOrViewContents<char> data(args[offset + 5]);
638
1487
  if (UNLIKELY(!data.CheckSizeInt32())) {
639
    THROW_ERR_OUT_OF_RANGE(env, "data is too big");
640
    return Nothing<bool>();
641
  }
642
  params->data = mode == kCryptoJobAsync
643
2974
      ? data.ToCopy()
644
1487
      : data.ToByteSource();
645
646

4461
  if (args[offset + 6]->IsString()) {
647
2746
    Utf8Value digest(env->isolate(), args[offset + 6]);
648
1373
    params->digest = EVP_get_digestbyname(*digest);
649
1373
    if (params->digest == nullptr) {
650
1
      THROW_ERR_CRYPTO_INVALID_DIGEST(env);
651
1
      return Nothing<bool>();
652
    }
653
  }
654
655

2972
  if (args[offset + 7]->IsInt32()) {  // Salt length
656
706
    params->flags |= SignConfiguration::kHasSaltLength;
657
2118
    params->salt_length = args[offset + 7].As<Int32>()->Value();
658
  }
659

2972
  if (args[offset + 8]->IsUint32()) {  // Padding
660
619
    params->flags |= SignConfiguration::kHasPadding;
661
1857
    params->padding = args[offset + 8].As<Uint32>()->Value();
662
  }
663
664

2972
  if (args[offset + 9]->IsUint32()) {  // DSA Encoding
665
1190
    params->dsa_encoding =
666
3570
        static_cast<DSASigEnc>(args[offset + 9].As<Uint32>()->Value());
667
1190
    if (params->dsa_encoding != kSigEncDER &&
668
286
        params->dsa_encoding != kSigEncP1363) {
669
      THROW_ERR_OUT_OF_RANGE(env, "invalid signature encoding");
670
      return Nothing<bool>();
671
    }
672
  }
673
674
1486
  if (params->mode == SignConfiguration::kVerify) {
675
2390
    ArrayBufferOrViewContents<char> signature(args[offset + 10]);
676
1195
    if (UNLIKELY(!signature.CheckSizeInt32())) {
677
      THROW_ERR_OUT_OF_RANGE(env, "signature is too big");
678
      return Nothing<bool>();
679
    }
680
    // If this is an EC key (assuming ECDSA) we need to convert the
681
    // the signature from WebCrypto format into DER format...
682
2390
    ManagedEVPPKey m_pkey = params->key;
683
2390
    Mutex::ScopedLock lock(*m_pkey.mutex());
684
1195
    if (UseP1363Encoding(m_pkey, params->dsa_encoding)) {
685
      params->signature =
686
230
          ConvertSignatureToDER(m_pkey, signature.ToByteSource());
687
    } else {
688
      params->signature = mode == kCryptoJobAsync
689
1930
          ? signature.ToCopy()
690
965
          : signature.ToByteSource();
691
    }
692
  }
693
694
1486
  return Just(true);
695
}
696
697
1486
bool SignTraits::DeriveBits(
698
    Environment* env,
699
    const SignConfiguration& params,
700
    ByteSource* out) {
701
1486
  ClearErrorOnReturn clear_error_on_return;
702
2972
  EVPMDPointer context(EVP_MD_CTX_new());
703
1486
  EVP_PKEY_CTX* ctx = nullptr;
704
705
1486
  switch (params.mode) {
706
291
    case SignConfiguration::kSign:
707
582
      if (!EVP_DigestSignInit(
708
              context.get(),
709
              &ctx,
710
291
              params.digest,
711
              nullptr,
712
              params.key.get())) {
713
6
        crypto::CheckThrow(env, SignBase::Error::kSignInit);
714
6
        return false;
715
      }
716
285
      break;
717
1195
    case SignConfiguration::kVerify:
718
2390
      if (!EVP_DigestVerifyInit(
719
              context.get(),
720
              &ctx,
721
1195
              params.digest,
722
              nullptr,
723
              params.key.get())) {
724
        crypto::CheckThrow(env, SignBase::Error::kSignInit);
725
        return false;
726
      }
727
1195
      break;
728
  }
729
730
1480
  int padding = params.flags & SignConfiguration::kHasPadding
731
1480
      ? params.padding
732
861
      : GetDefaultSignPadding(params.key);
733
734
1480
  Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength
735
1480
      ? Just<int>(params.salt_length) : Nothing<int>();
736
737
1480
  if (!ApplyRSAOptions(
738
1480
          params.key,
739
          ctx,
740
          padding,
741
          salt_length)) {
742
7
    crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
743
7
    return false;
744
  }
745
746
1473
  switch (params.mode) {
747
278
    case SignConfiguration::kSign: {
748
278
      if (IsOneShot(params.key)) {
749
        size_t len;
750
33
        if (!EVP_DigestSign(
751
            context.get(),
752
            nullptr,
753
            &len,
754
            params.data.data<unsigned char>(),
755
            params.data.size())) {
756
          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
757
          return false;
758
        }
759
33
        ByteSource::Builder buf(len);
760
33
        if (!EVP_DigestSign(context.get(),
761
                            buf.data<unsigned char>(),
762
                            &len,
763
                            params.data.data<unsigned char>(),
764
                            params.data.size())) {
765
          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
766
          return false;
767
        }
768
33
        *out = std::move(buf).release(len);
769
      } else {
770
        size_t len;
771
490
        if (!EVP_DigestSignUpdate(
772
                context.get(),
773
245
                params.data.data<unsigned char>(),
774

490
                params.data.size()) ||
775
245
            !EVP_DigestSignFinal(context.get(), nullptr, &len)) {
776
          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
777
1
          return false;
778
        }
779
245
        ByteSource::Builder buf(len);
780
245
        if (!EVP_DigestSignFinal(
781
                context.get(), buf.data<unsigned char>(), &len)) {
782
1
          crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
783
1
          return false;
784
        }
785
786
244
        if (UseP1363Encoding(params.key, params.dsa_encoding)) {
787
54
          *out = ConvertSignatureToP1363(
788
108
              env, params.key, std::move(buf).release());
789
        } else {
790
190
          *out = std::move(buf).release(len);
791
        }
792
      }
793
277
      break;
794
    }
795
1195
    case SignConfiguration::kVerify: {
796
1195
      ByteSource::Builder buf(1);
797
1195
      buf.data<char>()[0] = 0;
798
1195
      if (EVP_DigestVerify(
799
              context.get(),
800
              params.signature.data<unsigned char>(),
801
              params.signature.size(),
802
              params.data.data<unsigned char>(),
803
1195
              params.data.size()) == 1) {
804
653
        buf.data<char>()[0] = 1;
805
      }
806
1195
      *out = std::move(buf).release();
807
    }
808
  }
809
810
1472
  return true;
811
}
812
813
1472
Maybe<bool> SignTraits::EncodeOutput(
814
    Environment* env,
815
    const SignConfiguration& params,
816
    ByteSource* out,
817
    Local<Value>* result) {
818
1472
  switch (params.mode) {
819
277
    case SignConfiguration::kSign:
820
277
      *result = out->ToArrayBuffer(env);
821
277
      break;
822
1195
    case SignConfiguration::kVerify:
823
1195
      *result = out->data<char>()[0] == 1 ? v8::True(env->isolate())
824
542
                                          : v8::False(env->isolate());
825
1195
      break;
826
    default:
827
      UNREACHABLE();
828
  }
829
1472
  return Just(!result->IsEmpty());
830
}
831
832
}  // namespace crypto
833
}  // namespace node