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