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