GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_sig.cc Lines: 390 480 81.2 %
Date: 2022-06-15 16:51:59 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::Just;
21
using v8::Local;
22
using v8::Maybe;
23
using v8::Nothing;
24
using v8::Object;
25
using v8::Uint32;
26
using v8::Value;
27
28
namespace crypto {
29
namespace {
30
112
bool ValidateDSAParameters(EVP_PKEY* key) {
31
  /* Validate DSA2 parameters from FIPS 186-4 */
32
#if OPENSSL_VERSION_MAJOR >= 3
33

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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