GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_sig.cc Lines: 32 491 6.5 %
Date: 2021-02-19 04:08:54 Branches: 2 367 0.5 %

Line Branch Exec Source
1
#include "crypto/crypto_sig.h"
2
#include "crypto/crypto_ec.h"
3
#include "crypto/crypto_keys.h"
4
#include "crypto/crypto_util.h"
5
#include "allocated_buffer-inl.h"
6
#include "async_wrap-inl.h"
7
#include "base_object-inl.h"
8
#include "env-inl.h"
9
#include "memory_tracker-inl.h"
10
#include "threadpoolwork-inl.h"
11
#include "v8.h"
12
13
namespace node {
14
15
using v8::FunctionCallbackInfo;
16
using v8::FunctionTemplate;
17
using v8::HandleScope;
18
using v8::Int32;
19
using v8::Just;
20
using v8::Local;
21
using v8::Maybe;
22
using v8::Nothing;
23
using v8::Object;
24
using v8::Uint32;
25
using v8::Value;
26
27
namespace crypto {
28
namespace {
29
bool ValidateDSAParameters(EVP_PKEY* key) {
30
#ifdef NODE_FIPS_MODE
31
  /* Validate DSA2 parameters from FIPS 186-4 */
32
  if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
33
    DSA* dsa = EVP_PKEY_get0_DSA(key);
34
    const BIGNUM* p;
35
    DSA_get0_pqg(dsa, &p, nullptr, nullptr);
36
    size_t L = BN_num_bits(p);
37
    const BIGNUM* q;
38
    DSA_get0_pqg(dsa, nullptr, &q, nullptr);
39
    size_t N = BN_num_bits(q);
40
41
    return (L == 1024 && N == 160) ||
42
           (L == 2048 && N == 224) ||
43
           (L == 2048 && N == 256) ||
44
           (L == 3072 && N == 256);
45
  }
46
#endif  // NODE_FIPS_MODE
47
48
  return true;
49
}
50
51
bool ApplyRSAOptions(const ManagedEVPPKey& pkey,
52
                     EVP_PKEY_CTX* pkctx,
53
                     int padding,
54
                     const Maybe<int>& salt_len) {
55
  if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA ||
56
      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 ||
57
      EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) {
58
    if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0)
59
      return false;
60
    if (padding == RSA_PKCS1_PSS_PADDING && salt_len.IsJust()) {
61
      if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, salt_len.FromJust()) <= 0)
62
        return false;
63
    }
64
  }
65
66
  return true;
67
}
68
69
AllocatedBuffer Node_SignFinal(Environment* env,
70
                               EVPMDPointer&& mdctx,
71
                               const ManagedEVPPKey& pkey,
72
                               int padding,
73
                               Maybe<int> pss_salt_len) {
74
  unsigned char m[EVP_MAX_MD_SIZE];
75
  unsigned int m_len;
76
77
  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
78
    return AllocatedBuffer();
79
80
  int signed_sig_len = EVP_PKEY_size(pkey.get());
81
  CHECK_GE(signed_sig_len, 0);
82
  size_t sig_len = static_cast<size_t>(signed_sig_len);
83
  AllocatedBuffer sig = AllocatedBuffer::AllocateManaged(env, sig_len);
84
  unsigned char* ptr = reinterpret_cast<unsigned char*>(sig.data());
85
86
  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
87
  if (pkctx &&
88
      EVP_PKEY_sign_init(pkctx.get()) &&
89
      ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) &&
90
      EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) &&
91
      EVP_PKEY_sign(pkctx.get(), ptr, &sig_len, m, m_len)) {
92
    sig.Resize(sig_len);
93
    return sig;
94
  }
95
96
  return AllocatedBuffer();
97
}
98
99
int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) {
100
  return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING :
101
                                                         RSA_PKCS1_PADDING;
102
}
103
104
unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) {
105
  int bits, base_id = EVP_PKEY_base_id(pkey.get());
106
107
  if (base_id == EVP_PKEY_DSA) {
108
    DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get());
109
    // Both r and s are computed mod q, so their width is limited by that of q.
110
    bits = BN_num_bits(DSA_get0_q(dsa_key));
111
  } else if (base_id == EVP_PKEY_EC) {
112
    EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey.get());
113
    const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
114
    bits = EC_GROUP_order_bits(ec_group);
115
  } else {
116
    return kNoDsaSignature;
117
  }
118
119
  return (bits + 7) / 8;
120
}
121
122
// Returns the maximum size of each of the integers (r, s) of the DSA signature.
123
AllocatedBuffer ConvertSignatureToP1363(Environment* env,
124
                                        const ManagedEVPPKey& pkey,
125
                                        AllocatedBuffer&& signature) {
126
  unsigned int n = GetBytesOfRS(pkey);
127
  if (n == kNoDsaSignature)
128
    return std::move(signature);
129
130
  const unsigned char* sig_data =
131
      reinterpret_cast<unsigned char*>(signature.data());
132
133
  ECDSASigPointer asn1_sig(d2i_ECDSA_SIG(nullptr, &sig_data, signature.size()));
134
  if (!asn1_sig)
135
    return AllocatedBuffer();
136
137
  AllocatedBuffer buf = AllocatedBuffer::AllocateManaged(env, 2 * n);
138
  unsigned char* data = reinterpret_cast<unsigned char*>(buf.data());
139
140
  const BIGNUM* r = ECDSA_SIG_get0_r(asn1_sig.get());
141
  const BIGNUM* s = ECDSA_SIG_get0_s(asn1_sig.get());
142
  CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(r, data, n)));
143
  CHECK_EQ(n, static_cast<unsigned int>(BN_bn2binpad(s, data + n, n)));
144
145
  return buf;
146
}
147
148
149
ByteSource ConvertSignatureToDER(
150
      const ManagedEVPPKey& pkey,
151
      const ArrayBufferOrViewContents<char>& signature) {
152
  unsigned int n = GetBytesOfRS(pkey);
153
  if (n == kNoDsaSignature)
154
    return signature.ToByteSource();
155
156
  const unsigned char* sig_data =
157
      reinterpret_cast<const  unsigned char*>(signature.data());
158
159
  if (signature.size() != 2 * n)
160
    return ByteSource();
161
162
  ECDSASigPointer asn1_sig(ECDSA_SIG_new());
163
  CHECK(asn1_sig);
164
  BIGNUM* r = BN_new();
165
  CHECK_NOT_NULL(r);
166
  BIGNUM* s = BN_new();
167
  CHECK_NOT_NULL(s);
168
  CHECK_EQ(r, BN_bin2bn(sig_data, n, r));
169
  CHECK_EQ(s, BN_bin2bn(sig_data + n, n, s));
170
  CHECK_EQ(1, ECDSA_SIG_set0(asn1_sig.get(), r, s));
171
172
  unsigned char* data = nullptr;
173
  int len = i2d_ECDSA_SIG(asn1_sig.get(), &data);
174
175
  if (len <= 0)
176
    return ByteSource();
177
178
  CHECK_NOT_NULL(data);
179
180
  return ByteSource::Allocated(reinterpret_cast<char*>(data), len);
181
}
182
183
void CheckThrow(Environment* env, SignBase::Error error) {
184
  HandleScope scope(env->isolate());
185
186
  switch (error) {
187
    case SignBase::Error::kSignUnknownDigest:
188
      return THROW_ERR_CRYPTO_INVALID_DIGEST(env);
189
190
    case SignBase::Error::kSignNotInitialised:
191
      return THROW_ERR_CRYPTO_INVALID_STATE(env, "Not initialised");
192
193
    case SignBase::Error::kSignMalformedSignature:
194
      return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Malformed signature");
195
196
    case SignBase::Error::kSignInit:
197
    case SignBase::Error::kSignUpdate:
198
    case SignBase::Error::kSignPrivateKey:
199
    case SignBase::Error::kSignPublicKey:
200
      {
201
        unsigned long err = ERR_get_error();  // NOLINT(runtime/int)
202
        if (err)
203
          return ThrowCryptoError(env, err);
204
        switch (error) {
205
          case SignBase::Error::kSignInit:
206
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
207
                "EVP_SignInit_ex failed");
208
          case SignBase::Error::kSignUpdate:
209
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
210
                "EVP_SignUpdate failed");
211
          case SignBase::Error::kSignPrivateKey:
212
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
213
                "PEM_read_bio_PrivateKey failed");
214
          case SignBase::Error::kSignPublicKey:
215
            return THROW_ERR_CRYPTO_OPERATION_FAILED(env,
216
                "PEM_read_bio_PUBKEY failed");
217
          default:
218
            ABORT();
219
        }
220
      }
221
222
    case SignBase::Error::kSignOk:
223
      return;
224
  }
225
}
226
227
bool IsOneShot(const ManagedEVPPKey& key) {
228
  switch (EVP_PKEY_id(key.get())) {
229
    case EVP_PKEY_ED25519:
230
    case EVP_PKEY_ED448:
231
      return true;
232
    default:
233
      return false;
234
  }
235
}
236
}  // namespace
237
238
SignBase::Error SignBase::Init(const char* sign_type) {
239
  CHECK_NULL(mdctx_);
240
  // Historically, "dss1" and "DSS1" were DSA aliases for SHA-1
241
  // exposed through the public API.
242
  if (strcmp(sign_type, "dss1") == 0 ||
243
      strcmp(sign_type, "DSS1") == 0) {
244
    sign_type = "SHA1";
245
  }
246
  const EVP_MD* md = EVP_get_digestbyname(sign_type);
247
  if (md == nullptr)
248
    return kSignUnknownDigest;
249
250
  mdctx_.reset(EVP_MD_CTX_new());
251
  if (!mdctx_ || !EVP_DigestInit_ex(mdctx_.get(), md, nullptr)) {
252
    mdctx_.reset();
253
    return kSignInit;
254
  }
255
256
  return kSignOk;
257
}
258
259
SignBase::Error SignBase::Update(const char* data, size_t len) {
260
  if (mdctx_ == nullptr)
261
    return kSignNotInitialised;
262
  if (!EVP_DigestUpdate(mdctx_.get(), data, len))
263
    return kSignUpdate;
264
  return kSignOk;
265
}
266
267
SignBase::SignBase(Environment* env, Local<Object> wrap)
268
    : BaseObject(env, wrap) {}
269
270
void SignBase::MemoryInfo(MemoryTracker* tracker) const {
271
  tracker->TrackFieldWithSize("mdctx", mdctx_ ? kSizeOf_EVP_MD_CTX : 0);
272
}
273
274
Sign::Sign(Environment* env, Local<Object> wrap) : SignBase(env, wrap) {
275
  MakeWeak();
276
}
277
278
2
void Sign::Initialize(Environment* env, Local<Object> target) {
279
2
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
280
281
6
  t->InstanceTemplate()->SetInternalFieldCount(
282
2
      SignBase::kInternalFieldCount);
283
4
  t->Inherit(BaseObject::GetConstructorTemplate(env));
284
285
2
  env->SetProtoMethod(t, "init", SignInit);
286
2
  env->SetProtoMethod(t, "update", SignUpdate);
287
2
  env->SetProtoMethod(t, "sign", SignFinal);
288
289
2
  env->SetConstructorFunction(target, "Sign", t);
290
291
2
  env->SetMethod(target, "signOneShot", Sign::SignSync);
292
293
2
  SignJob::Initialize(env, target);
294
295
2
  constexpr int kSignJobModeSign = SignConfiguration::kSign;
296
2
  constexpr int kSignJobModeVerify = SignConfiguration::kVerify;
297
298
8
  NODE_DEFINE_CONSTANT(target, kSignJobModeSign);
299
2
  NODE_DEFINE_CONSTANT(target, kSignJobModeVerify);
300
6
  NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PSS_PADDING);
301
10
}
302
14
303
10
void Sign::New(const FunctionCallbackInfo<Value>& args) {
304
4
  Environment* env = Environment::GetCurrent(args);
305
  new Sign(env, args.This());
306
}
307
308
void Sign::SignInit(const FunctionCallbackInfo<Value>& args) {
309
  Environment* env = Environment::GetCurrent(args);
310
  Sign* sign;
311
  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
312
313
  const node::Utf8Value sign_type(args.GetIsolate(), args[0]);
314
  crypto::CheckThrow(env, sign->Init(*sign_type));
315
}
316
317
void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
318
  Decode<Sign>(args, [](Sign* sign, const FunctionCallbackInfo<Value>& args,
319
                        const char* data, size_t size) {
320
    Environment* env = Environment::GetCurrent(args);
321
    if (UNLIKELY(size > INT_MAX))
322
      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
323
    Error err = sign->Update(data, size);
324
    crypto::CheckThrow(sign->env(), err);
325
  });
326
}
327
328
Sign::SignResult Sign::SignFinal(
329
    const ManagedEVPPKey& pkey,
330
    int padding,
331
    const Maybe<int>& salt_len,
332
    DSASigEnc dsa_sig_enc) {
333
  if (!mdctx_)
334
    return SignResult(kSignNotInitialised);
335
336
  EVPMDPointer mdctx = std::move(mdctx_);
337
338
  if (!ValidateDSAParameters(pkey.get()))
339
    return SignResult(kSignPrivateKey);
340
341
  AllocatedBuffer buffer =
342
      Node_SignFinal(env(), std::move(mdctx), pkey, padding, salt_len);
343
  Error error = buffer.data() == nullptr ? kSignPrivateKey : kSignOk;
344
  if (error == kSignOk && dsa_sig_enc == kSigEncP1363) {
345
    buffer = ConvertSignatureToP1363(env(), pkey, std::move(buffer));
346
    CHECK_NOT_NULL(buffer.data());
347
  }
348
  return SignResult(error, std::move(buffer));
349
}
350
351
void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
352
  Environment* env = Environment::GetCurrent(args);
353
  Sign* sign;
354
  ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());
355
356
  ClearErrorOnReturn clear_error_on_return;
357
358
  unsigned int offset = 0;
359
  ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true);
360
  if (!key)
361
    return;
362
363
  int padding = GetDefaultSignPadding(key);
364
  if (!args[offset]->IsUndefined()) {
365
    CHECK(args[offset]->IsInt32());
366
    padding = args[offset].As<Int32>()->Value();
367
  }
368
369
  Maybe<int> salt_len = Nothing<int>();
370
  if (!args[offset + 1]->IsUndefined()) {
371
    CHECK(args[offset + 1]->IsInt32());
372
    salt_len = Just<int>(args[offset + 1].As<Int32>()->Value());
373
  }
374
375
  CHECK(args[offset + 2]->IsInt32());
376
  DSASigEnc dsa_sig_enc =
377
      static_cast<DSASigEnc>(args[offset + 2].As<Int32>()->Value());
378
379
  SignResult ret = sign->SignFinal(
380
      key,
381
      padding,
382
      salt_len,
383
      dsa_sig_enc);
384
385
  if (ret.error != kSignOk)
386
    return crypto::CheckThrow(env, ret.error);
387
388
  args.GetReturnValue().Set(ret.signature.ToBuffer().FromMaybe(Local<Value>()));
389
}
390
391
Verify::Verify(Environment* env, Local<Object> wrap)
392
  : SignBase(env, wrap) {
393
  MakeWeak();
394
}
395
396
2
void Verify::Initialize(Environment* env, Local<Object> target) {
397
2
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
398
399
6
  t->InstanceTemplate()->SetInternalFieldCount(
400
2
      SignBase::kInternalFieldCount);
401
4
  t->Inherit(BaseObject::GetConstructorTemplate(env));
402
403
2
  env->SetProtoMethod(t, "init", VerifyInit);
404
2
  env->SetProtoMethod(t, "update", VerifyUpdate);
405
2
  env->SetProtoMethod(t, "verify", VerifyFinal);
406
407
2
  env->SetConstructorFunction(target, "Verify", t);
408
409
2
  env->SetMethod(target, "verifyOneShot", Verify::VerifySync);
410
2
}
411
412
void Verify::New(const FunctionCallbackInfo<Value>& args) {
413
  Environment* env = Environment::GetCurrent(args);
414
  new Verify(env, args.This());
415
}
416
417
void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
418
  Environment* env = Environment::GetCurrent(args);
419
  Verify* verify;
420
  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
421
422
  const node::Utf8Value verify_type(args.GetIsolate(), args[0]);
423
  crypto::CheckThrow(env, verify->Init(*verify_type));
424
}
425
426
void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
427
  Decode<Verify>(args, [](Verify* verify,
428
                          const FunctionCallbackInfo<Value>& args,
429
                          const char* data, size_t size) {
430
    Environment* env = Environment::GetCurrent(args);
431
    if (UNLIKELY(size > INT_MAX))
432
      return THROW_ERR_OUT_OF_RANGE(env, "data is too long");
433
    Error err = verify->Update(data, size);
434
    crypto::CheckThrow(verify->env(), err);
435
  });
436
}
437
438
SignBase::Error Verify::VerifyFinal(const ManagedEVPPKey& pkey,
439
                                    const ByteSource& sig,
440
                                    int padding,
441
                                    const Maybe<int>& saltlen,
442
                                    bool* verify_result) {
443
  if (!mdctx_)
444
    return kSignNotInitialised;
445
446
  unsigned char m[EVP_MAX_MD_SIZE];
447
  unsigned int m_len;
448
  *verify_result = false;
449
  EVPMDPointer mdctx = std::move(mdctx_);
450
451
  if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
452
    return kSignPublicKey;
453
454
  EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
455
  if (pkctx &&
456
      EVP_PKEY_verify_init(pkctx.get()) > 0 &&
457
      ApplyRSAOptions(pkey, pkctx.get(), padding, saltlen) &&
458
      EVP_PKEY_CTX_set_signature_md(pkctx.get(),
459
                                    EVP_MD_CTX_md(mdctx.get())) > 0) {
460
    const unsigned char* s = reinterpret_cast<const unsigned char*>(sig.get());
461
    const int r = EVP_PKEY_verify(pkctx.get(), s, sig.size(), m, m_len);
462
    *verify_result = r == 1;
463
  }
464
465
  return kSignOk;
466
}
467
468
void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
469
  Environment* env = Environment::GetCurrent(args);
470
  ClearErrorOnReturn clear_error_on_return;
471
472
  Verify* verify;
473
  ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
474
475
  unsigned int offset = 0;
476
  ManagedEVPPKey pkey =
477
      ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
478
  if (!pkey)
479
    return;
480
481
  ArrayBufferOrViewContents<char> hbuf(args[offset]);
482
  if (UNLIKELY(!hbuf.CheckSizeInt32()))
483
    return THROW_ERR_OUT_OF_RANGE(env, "buffer is too big");
484
485
  int padding = GetDefaultSignPadding(pkey);
486
  if (!args[offset + 1]->IsUndefined()) {
487
    CHECK(args[offset + 1]->IsInt32());
488
    padding = args[offset + 1].As<Int32>()->Value();
489
  }
490
491
  Maybe<int> salt_len = Nothing<int>();
492
  if (!args[offset + 2]->IsUndefined()) {
493
    CHECK(args[offset + 2]->IsInt32());
494
    salt_len = Just<int>(args[offset + 2].As<Int32>()->Value());
495
  }
496
497
  CHECK(args[offset + 3]->IsInt32());
498
  DSASigEnc dsa_sig_enc =
499
      static_cast<DSASigEnc>(args[offset + 3].As<Int32>()->Value());
500
501
  ByteSource signature = hbuf.ToByteSource();
502
  if (dsa_sig_enc == kSigEncP1363) {
503
    signature = ConvertSignatureToDER(pkey, hbuf);
504
    if (signature.get() == nullptr)
505
      return crypto::CheckThrow(env, Error::kSignMalformedSignature);
506
  }
507
508
  bool verify_result;
509
  Error err = verify->VerifyFinal(pkey, signature, padding,
510
                                  salt_len, &verify_result);
511
  if (err != kSignOk)
512
    return crypto::CheckThrow(env, err);
513
  args.GetReturnValue().Set(verify_result);
514
}
515
516
void Sign::SignSync(const FunctionCallbackInfo<Value>& args) {
517
  ClearErrorOnReturn clear_error_on_return;
518
  Environment* env = Environment::GetCurrent(args);
519
520
  unsigned int offset = 0;
521
  ManagedEVPPKey key = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, true);
522
  if (!key)
523
    return;
524
525
  if (!ValidateDSAParameters(key.get()))
526
    return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
527
528
  ArrayBufferOrViewContents<char> data(args[offset]);
529
  if (UNLIKELY(!data.CheckSizeInt32()))
530
    return THROW_ERR_OUT_OF_RANGE(env, "data is too big");
531
532
  const EVP_MD* md;
533
  if (args[offset + 1]->IsNullOrUndefined()) {
534
    md = nullptr;
535
  } else {
536
    const node::Utf8Value sign_type(args.GetIsolate(), args[offset + 1]);
537
    md = EVP_get_digestbyname(*sign_type);
538
    if (md == nullptr)
539
      return crypto::CheckThrow(env, SignBase::Error::kSignUnknownDigest);
540
  }
541
542
  int rsa_padding = GetDefaultSignPadding(key);
543
  if (!args[offset + 2]->IsUndefined()) {
544
    CHECK(args[offset + 2]->IsInt32());
545
    rsa_padding = args[offset + 2].As<Int32>()->Value();
546
  }
547
548
  Maybe<int> rsa_salt_len = Nothing<int>();
549
  if (!args[offset + 3]->IsUndefined()) {
550
    CHECK(args[offset + 3]->IsInt32());
551
    rsa_salt_len = Just<int>(args[offset + 3].As<Int32>()->Value());
552
  }
553
554
  CHECK(args[offset + 4]->IsInt32());
555
  DSASigEnc dsa_sig_enc =
556
      static_cast<DSASigEnc>(args[offset + 4].As<Int32>()->Value());
557
558
  EVP_PKEY_CTX* pkctx = nullptr;
559
  EVPMDPointer mdctx(EVP_MD_CTX_new());
560
561
  if (!mdctx ||
562
      !EVP_DigestSignInit(mdctx.get(), &pkctx, md, nullptr, key.get())) {
563
    return crypto::CheckThrow(env, SignBase::Error::kSignInit);
564
  }
565
566
  if (!ApplyRSAOptions(key, pkctx, rsa_padding, rsa_salt_len))
567
    return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
568
569
  const unsigned char* input =
570
    reinterpret_cast<const unsigned char*>(data.data());
571
  size_t sig_len;
572
  if (!EVP_DigestSign(mdctx.get(), nullptr, &sig_len, input, data.size()))
573
    return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
574
575
  AllocatedBuffer signature = AllocatedBuffer::AllocateManaged(env, sig_len);
576
  if (!EVP_DigestSign(mdctx.get(),
577
                      reinterpret_cast<unsigned char*>(signature.data()),
578
                      &sig_len,
579
                      input,
580
                      data.size())) {
581
    return crypto::CheckThrow(env, SignBase::Error::kSignPrivateKey);
582
  }
583
584
  signature.Resize(sig_len);
585
586
  if (dsa_sig_enc == kSigEncP1363) {
587
    signature = ConvertSignatureToP1363(env, key, std::move(signature));
588
  }
589
590
  args.GetReturnValue().Set(signature.ToBuffer().FromMaybe(Local<Value>()));
591
}
592
593
void Verify::VerifySync(const FunctionCallbackInfo<Value>& args) {
594
  ClearErrorOnReturn clear_error_on_return;
595
  Environment* env = Environment::GetCurrent(args);
596
597
  unsigned int offset = 0;
598
  ManagedEVPPKey key =
599
      ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
600
  if (!key)
601
    return;
602
603
  ArrayBufferOrViewContents<char> sig(args[offset]);
604
  ArrayBufferOrViewContents<char> data(args[offset + 1]);
605
606
  if (UNLIKELY(!sig.CheckSizeInt32()))
607
    return THROW_ERR_OUT_OF_RANGE(env, "sig is too big");
608
  if (UNLIKELY(!data.CheckSizeInt32()))
609
    return THROW_ERR_OUT_OF_RANGE(env, "data is too big");
610
611
  const EVP_MD* md;
612
  if (args[offset + 2]->IsNullOrUndefined()) {
613
    md = nullptr;
614
  } else {
615
    const node::Utf8Value sign_type(args.GetIsolate(), args[offset + 2]);
616
    md = EVP_get_digestbyname(*sign_type);
617
    if (md == nullptr)
618
      return crypto::CheckThrow(env, SignBase::Error::kSignUnknownDigest);
619
  }
620
621
  int rsa_padding = GetDefaultSignPadding(key);
622
  if (!args[offset + 3]->IsUndefined()) {
623
    CHECK(args[offset + 3]->IsInt32());
624
    rsa_padding = args[offset + 3].As<Int32>()->Value();
625
  }
626
627
  Maybe<int> rsa_salt_len = Nothing<int>();
628
  if (!args[offset + 4]->IsUndefined()) {
629
    CHECK(args[offset + 4]->IsInt32());
630
    rsa_salt_len = Just<int>(args[offset + 4].As<Int32>()->Value());
631
  }
632
633
  CHECK(args[offset + 5]->IsInt32());
634
  DSASigEnc dsa_sig_enc =
635
      static_cast<DSASigEnc>(args[offset + 5].As<Int32>()->Value());
636
637
  EVP_PKEY_CTX* pkctx = nullptr;
638
  EVPMDPointer mdctx(EVP_MD_CTX_new());
639
  if (!mdctx ||
640
      !EVP_DigestVerifyInit(mdctx.get(), &pkctx, md, nullptr, key.get())) {
641
    return crypto::CheckThrow(env, SignBase::Error::kSignInit);
642
  }
643
644
  if (!ApplyRSAOptions(key, pkctx, rsa_padding, rsa_salt_len))
645
    return crypto::CheckThrow(env, SignBase::Error::kSignPublicKey);
646
647
  ByteSource sig_bytes = ByteSource::Foreign(sig.data(), sig.size());
648
  if (dsa_sig_enc == kSigEncP1363) {
649
    sig_bytes = ConvertSignatureToDER(key, sig);
650
    if (!sig_bytes)
651
      return crypto::CheckThrow(env, SignBase::Error::kSignMalformedSignature);
652
  }
653
654
  bool verify_result;
655
  const int r = EVP_DigestVerify(
656
    mdctx.get(),
657
    sig_bytes.data<unsigned char>(),
658
    sig_bytes.size(),
659
    reinterpret_cast<const unsigned char*>(data.data()),
660
    data.size());
661
  switch (r) {
662
    case 1:
663
      verify_result = true;
664
      break;
665
    case 0:
666
      verify_result = false;
667
      break;
668
    default:
669
      return crypto::CheckThrow(env, SignBase::Error::kSignPublicKey);
670
  }
671
672
  args.GetReturnValue().Set(verify_result);
673
}
674
675
SignConfiguration::SignConfiguration(SignConfiguration&& other) noexcept
676
    : job_mode(other.job_mode),
677
      mode(other.mode),
678
      key(std::move(other.key)),
679
      data(std::move(other.data)),
680
      signature(std::move(other.signature)),
681
      digest(other.digest),
682
      flags(other.flags),
683
      padding(other.padding),
684
      salt_length(other.salt_length) {}
685
686
SignConfiguration& SignConfiguration::operator=(
687
    SignConfiguration&& other) noexcept {
688
  if (&other == this) return *this;
689
  this->~SignConfiguration();
690
  return *new (this) SignConfiguration(std::move(other));
691
}
692
693
void SignConfiguration::MemoryInfo(MemoryTracker* tracker) const {
694
  tracker->TrackField("key", key.get());
695
  if (job_mode == kCryptoJobAsync) {
696
    tracker->TrackFieldWithSize("data", data.size());
697
    tracker->TrackFieldWithSize("signature", signature.size());
698
  }
699
}
700
701
Maybe<bool> SignTraits::AdditionalConfig(
702
    CryptoJobMode mode,
703
    const FunctionCallbackInfo<Value>& args,
704
    unsigned int offset,
705
    SignConfiguration* params) {
706
  Environment* env = Environment::GetCurrent(args);
707
708
  params->job_mode = mode;
709
710
  CHECK(args[offset]->IsUint32());  // Sign Mode
711
  CHECK(args[offset + 1]->IsObject());  // Key
712
713
  params->mode =
714
      static_cast<SignConfiguration::Mode>(args[offset].As<Uint32>()->Value());
715
716
  KeyObjectHandle* key;
717
  ASSIGN_OR_RETURN_UNWRAP(&key, args[offset + 1], Nothing<bool>());
718
  params->key = key->Data();
719
720
  ArrayBufferOrViewContents<char> data(args[offset + 2]);
721
  if (UNLIKELY(!data.CheckSizeInt32())) {
722
    THROW_ERR_OUT_OF_RANGE(env, "data is too big");
723
    return Nothing<bool>();
724
  }
725
  params->data = mode == kCryptoJobAsync
726
      ? data.ToCopy()
727
      : data.ToByteSource();
728
729
  if (args[offset + 3]->IsString()) {
730
    Utf8Value digest(env->isolate(), args[offset + 3]);
731
    params->digest = EVP_get_digestbyname(*digest);
732
    if (params->digest == nullptr) {
733
      THROW_ERR_CRYPTO_INVALID_DIGEST(env);
734
      return Nothing<bool>();
735
    }
736
  }
737
738
  if (args[offset + 4]->IsUint32()) {  // Salt length
739
    params->flags |= SignConfiguration::kHasSaltLength;
740
    params->salt_length = args[offset + 4].As<Uint32>()->Value();
741
  }
742
  if (args[offset + 5]->IsUint32()) {  // Padding
743
    params->flags |= SignConfiguration::kHasPadding;
744
    params->padding = args[offset + 5].As<Uint32>()->Value();
745
  }
746
747
  if (params->mode == SignConfiguration::kVerify) {
748
    ArrayBufferOrViewContents<char> signature(args[offset + 6]);
749
    if (UNLIKELY(!signature.CheckSizeInt32())) {
750
      THROW_ERR_OUT_OF_RANGE(env, "signature is too big");
751
      return Nothing<bool>();
752
    }
753
    // If this is an EC key (assuming ECDSA) we need to convert the
754
    // the signature from WebCrypto format into DER format...
755
    ManagedEVPPKey m_pkey = params->key->GetAsymmetricKey();
756
    Mutex::ScopedLock lock(*m_pkey.mutex());
757
    if (EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_EC) {
758
      params->signature =
759
          ConvertFromWebCryptoSignature(m_pkey, signature.ToByteSource());
760
    } else {
761
      params->signature = mode == kCryptoJobAsync
762
          ? signature.ToCopy()
763
          : signature.ToByteSource();
764
    }
765
  }
766
767
  return Just(true);
768
}
769
770
bool SignTraits::DeriveBits(
771
    Environment* env,
772
    const SignConfiguration& params,
773
    ByteSource* out) {
774
  EVPMDPointer context(EVP_MD_CTX_new());
775
  EVP_PKEY_CTX* ctx = nullptr;
776
777
  ManagedEVPPKey m_pkey = params.key->GetAsymmetricKey();
778
  Mutex::ScopedLock lock(*m_pkey.mutex());
779
  switch (params.mode) {
780
    case SignConfiguration::kSign:
781
      CHECK_EQ(params.key->GetKeyType(), kKeyTypePrivate);
782
      if (!EVP_DigestSignInit(
783
              context.get(),
784
              &ctx,
785
              params.digest,
786
              nullptr,
787
              m_pkey.get())) {
788
        return false;
789
      }
790
      break;
791
    case SignConfiguration::kVerify:
792
      CHECK_EQ(params.key->GetKeyType(), kKeyTypePublic);
793
      if (!EVP_DigestVerifyInit(
794
              context.get(),
795
              &ctx,
796
              params.digest,
797
              nullptr,
798
              m_pkey.get())) {
799
        return false;
800
      }
801
      break;
802
  }
803
804
  int padding = params.flags & SignConfiguration::kHasPadding
805
      ? params.padding
806
      : GetDefaultSignPadding(m_pkey);
807
808
  Maybe<int> salt_length = params.flags & SignConfiguration::kHasSaltLength
809
      ? Just<int>(params.salt_length) : Nothing<int>();
810
811
  if (!ApplyRSAOptions(
812
          m_pkey,
813
          ctx,
814
          padding,
815
          salt_length)) {
816
    return false;
817
  }
818
819
  switch (params.mode) {
820
    case SignConfiguration::kSign: {
821
      size_t len;
822
      unsigned char* data = nullptr;
823
      if (IsOneShot(params.key->GetAsymmetricKey())) {
824
        EVP_DigestSign(
825
            context.get(),
826
            nullptr,
827
            &len,
828
            params.data.data<unsigned char>(),
829
            params.data.size());
830
        data = MallocOpenSSL<unsigned char>(len);
831
        EVP_DigestSign(
832
            context.get(),
833
            data,
834
            &len,
835
            params.data.data<unsigned char>(),
836
            params.data.size());
837
        ByteSource buf =
838
            ByteSource::Allocated(reinterpret_cast<char*>(data), len);
839
        *out = std::move(buf);
840
      } else {
841
        if (!EVP_DigestSignUpdate(
842
                context.get(),
843
                params.data.data<unsigned char>(),
844
                params.data.size()) ||
845
            !EVP_DigestSignFinal(context.get(), nullptr, &len)) {
846
          return false;
847
        }
848
        data = MallocOpenSSL<unsigned char>(len);
849
        ByteSource buf =
850
            ByteSource::Allocated(reinterpret_cast<char*>(data), len);
851
        if (!EVP_DigestSignFinal(context.get(), data, &len))
852
          return false;
853
854
        // If this is an EC key (assuming ECDSA) we have to
855
        // convert the signature in to the proper format.
856
        if (EVP_PKEY_id(params.key->GetAsymmetricKey().get()) == EVP_PKEY_EC) {
857
          *out = ConvertToWebCryptoSignature(
858
              params.key->GetAsymmetricKey(), buf);
859
        } else {
860
          buf.Resize(len);
861
          *out = std::move(buf);
862
        }
863
      }
864
      break;
865
    }
866
    case SignConfiguration::kVerify: {
867
      char* data = MallocOpenSSL<char>(1);
868
      data[0] = 0;
869
      *out = ByteSource::Allocated(data, 1);
870
      if (EVP_DigestVerify(
871
              context.get(),
872
              params.signature.data<unsigned char>(),
873
              params.signature.size(),
874
              params.data.data<unsigned char>(),
875
              params.data.size()) == 1) {
876
        data[0] = 1;
877
      }
878
    }
879
  }
880
881
  return true;
882
}
883
884
Maybe<bool> SignTraits::EncodeOutput(
885
    Environment* env,
886
    const SignConfiguration& params,
887
    ByteSource* out,
888
    Local<Value>* result) {
889
  switch (params.mode) {
890
    case SignConfiguration::kSign:
891
      *result = out->ToArrayBuffer(env);
892
      break;
893
    case SignConfiguration::kVerify:
894
      *result = out->get()[0] == 1
895
          ? v8::True(env->isolate())
896
          : v8::False(env->isolate());
897
      break;
898
    default:
899
      UNREACHABLE();
900
  }
901
  return Just(!result->IsEmpty());
902
}
903
904
}  // namespace crypto
905

366
}  // namespace node