11
11
12
12
namespace node {
13
13
14
+ using ncrypto::DataPointer;
14
15
using ncrypto::EVPMDCtxPointer;
15
16
using ncrypto::MarkPopErrorOnReturn;
16
17
using v8::Context;
@@ -220,7 +221,7 @@ void Hash::OneShotDigest(const FunctionCallbackInfo<Value>& args) {
220
221
CHECK (args[5 ]->IsUint32 () || args[5 ]->IsUndefined ()); // outputEncodingId
221
222
222
223
const EVP_MD* md = GetDigestImplementation (env, args[0 ], args[1 ], args[2 ]);
223
- if (md == nullptr ) {
224
+ if (md == nullptr ) [[unlikely]] {
224
225
Utf8Value method (isolate, args[0 ]);
225
226
std::string message =
226
227
" Digest method " + method.ToString () + " is not supported" ;
@@ -229,41 +230,36 @@ void Hash::OneShotDigest(const FunctionCallbackInfo<Value>& args) {
229
230
230
231
enum encoding output_enc = ParseEncoding (isolate, args[4 ], args[5 ], HEX);
231
232
232
- int md_len = EVP_MD_size (md);
233
- unsigned int result_size;
234
- ByteSource::Builder output (md_len);
235
- int success;
236
- // On smaller inputs, EVP_Digest() can be slower than the
237
- // deprecated helpers e.g SHA256_XXX. The speedup may not
238
- // be worth using deprecated APIs, however, so we use
239
- // EVP_Digest(), unless there's a better alternative
240
- // in the future.
241
- // https://github.com/openssl/openssl/issues/19612
242
- if (args[3 ]->IsString ()) {
243
- Utf8Value utf8 (isolate, args[3 ]);
244
- success = EVP_Digest (utf8.out (),
245
- utf8.length (),
246
- output.data <unsigned char >(),
247
- &result_size,
248
- md,
249
- nullptr );
250
- } else {
233
+ DataPointer output = ([&] {
234
+ if (args[3 ]->IsString ()) {
235
+ Utf8Value utf8 (isolate, args[3 ]);
236
+ ncrypto::Buffer<const unsigned char > buf{
237
+ .data = reinterpret_cast <const unsigned char *>(utf8.out ()),
238
+ .len = utf8.length (),
239
+ };
240
+ return ncrypto::hashDigest (buf, md);
241
+ }
242
+
251
243
ArrayBufferViewContents<unsigned char > input (args[3 ]);
252
- success = EVP_Digest (input. data (),
253
- input.length ( ),
254
- output. data < unsigned char > (),
255
- &result_size,
256
- md,
257
- nullptr );
258
- }
259
- if (!success) {
244
+ ncrypto::Buffer< const unsigned char > buf{
245
+ . data = reinterpret_cast < const unsigned char *>( input.data () ),
246
+ . len = input. length (),
247
+ };
248
+ return ncrypto::hashDigest (buf, md);
249
+ })( );
250
+
251
+ if (!output) [[unlikely]] {
260
252
return ThrowCryptoError (env, ERR_get_error ());
261
253
}
262
254
263
255
Local<Value> error;
264
- MaybeLocal<Value> rc = StringBytes::Encode (
265
- env->isolate (), output.data <char >(), md_len, output_enc, &error);
266
- if (rc.IsEmpty ()) {
256
+ MaybeLocal<Value> rc =
257
+ StringBytes::Encode (env->isolate (),
258
+ static_cast <const char *>(output.get ()),
259
+ output.size (),
260
+ output_enc,
261
+ &error);
262
+ if (rc.IsEmpty ()) [[unlikely]] {
267
263
CHECK (!error.IsEmpty ());
268
264
env->isolate ()->ThrowException (error);
269
265
return ;
@@ -339,7 +335,7 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) {
339
335
340
336
bool Hash::HashInit (const EVP_MD* md, Maybe<unsigned int > xof_md_len) {
341
337
mdctx_ = EVPMDCtxPointer::New ();
342
- if (!mdctx_.digestInit (md)) {
338
+ if (!mdctx_.digestInit (md)) [[unlikely]] {
343
339
mdctx_.reset ();
344
340
return false ;
345
341
}
@@ -348,7 +344,7 @@ bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) {
348
344
if (xof_md_len.IsJust () && xof_md_len.FromJust () != md_len_) {
349
345
// This is a little hack to cause createHash to fail when an incorrect
350
346
// hashSize option was passed for a non-XOF hash function.
351
- if (!mdctx_.hasXofFlag ()) {
347
+ if (!mdctx_.hasXofFlag ()) [[unlikely]] {
352
348
EVPerr (EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
353
349
mdctx_.reset ();
354
350
return false ;
@@ -406,7 +402,7 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
406
402
// so we need to cache it.
407
403
// See https://github.com/nodejs/node/issues/28245.
408
404
auto data = hash->mdctx_ .digestFinal (len);
409
- if (!data) {
405
+ if (!data) [[unlikely]] {
410
406
return ThrowCryptoError (env, ERR_get_error ());
411
407
}
412
408
@@ -416,7 +412,7 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
416
412
Local<Value> error;
417
413
MaybeLocal<Value> rc = StringBytes::Encode (
418
414
env->isolate (), hash->digest_ .data <char >(), len, encoding, &error);
419
- if (rc.IsEmpty ()) {
415
+ if (rc.IsEmpty ()) [[unlikely]] {
420
416
CHECK (!error.IsEmpty ());
421
417
env->isolate ()->ThrowException (error);
422
418
return ;
@@ -482,7 +478,7 @@ Maybe<void> HashTraits::AdditionalConfig(
482
478
static_cast <uint32_t >(args[offset + 2 ]
483
479
.As <Uint32>()->Value ()) / CHAR_BIT;
484
480
if (params->length != expected) {
485
- if ((EVP_MD_flags (params->digest ) & EVP_MD_FLAG_XOF) == 0 ) {
481
+ if ((EVP_MD_flags (params->digest ) & EVP_MD_FLAG_XOF) == 0 ) [[unlikely]] {
486
482
THROW_ERR_CRYPTO_INVALID_DIGEST (env, " Digest method not supported" );
487
483
return Nothing<void >();
488
484
}
@@ -505,7 +501,8 @@ bool HashTraits::DeriveBits(
505
501
506
502
if (params.length > 0 ) [[likely]] {
507
503
auto data = ctx.digestFinal (params.length );
508
- if (!data) return false ;
504
+ if (!data) [[unlikely]]
505
+ return false ;
509
506
510
507
*out = ByteSource::Allocated (data.release ());
511
508
}
@@ -535,7 +532,7 @@ void InternalVerifyIntegrity(const v8::FunctionCallbackInfo<v8::Value>& args) {
535
532
digest,
536
533
&digest_size,
537
534
md_type,
538
- nullptr ) != 1 ) {
535
+ nullptr ) != 1 ) [[unlikely]] {
539
536
return ThrowCryptoError (
540
537
env, ERR_get_error (), " Digest method not supported" );
541
538
}
@@ -549,7 +546,7 @@ void InternalVerifyIntegrity(const v8::FunctionCallbackInfo<v8::Value>& args) {
549
546
digest_size,
550
547
BASE64,
551
548
&error);
552
- if (rc.IsEmpty ()) {
549
+ if (rc.IsEmpty ()) [[unlikely]] {
553
550
CHECK (!error.IsEmpty ());
554
551
env->isolate ()->ThrowException (error);
555
552
return ;
0 commit comments