Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 953a850

Browse filesBrowse files
tniessenrichardlau
authored andcommitted
crypto: fix crash when calling digest after piping
When piping data into an SHA3 hash, EVP_DigestFinal_ex is called in hash._flush, bypassing safeguards in the JavaScript layer. Calling hash.digest causes EVP_DigestFinal_ex to be called again, resulting in a segmentation fault in the SHA3 implementation of OpenSSL. A relatively easy solution is to cache the result of calling EVP_DigestFinal_ex until the Hash object is garbage collected. PR-URL: #28251 Fixes: #28245 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Backport-PR-URL: #37009 Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: Shelley Vohr <codebytere@gmail.com>
1 parent 68a6b8d commit 953a850
Copy full SHA for 953a850

File tree

Expand file treeCollapse file tree

2 files changed

+18
-7
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+18
-7
lines changed
Open diff view settings
Collapse file

‎src/node_crypto.cc‎

Copy file name to clipboardExpand all lines: src/node_crypto.cc
+10-6Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3419,16 +3419,20 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
34193419
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
34203420
}
34213421

3422-
unsigned char md_value[EVP_MAX_MD_SIZE];
3423-
unsigned int md_len;
3424-
3425-
EVP_DigestFinal_ex(hash->mdctx_.get(), md_value, &md_len);
3422+
if (hash->md_len_ == 0) {
3423+
// Some hash algorithms such as SHA3 do not support calling
3424+
// EVP_DigestFinal_ex more than once, however, Hash._flush
3425+
// and Hash.digest can both be used to retrieve the digest,
3426+
// so we need to cache it.
3427+
// See https://github.com/nodejs/node/issues/28245.
3428+
EVP_DigestFinal_ex(hash->mdctx_.get(), hash->md_value_, &hash->md_len_);
3429+
}
34263430

34273431
Local<Value> error;
34283432
MaybeLocal<Value> rc =
34293433
StringBytes::Encode(env->isolate(),
3430-
reinterpret_cast<const char*>(md_value),
3431-
md_len,
3434+
reinterpret_cast<const char*>(hash->md_value_),
3435+
hash->md_len_,
34323436
encoding,
34333437
&error);
34343438
if (rc.IsEmpty()) {
Collapse file

‎src/node_crypto.h‎

Copy file name to clipboardExpand all lines: src/node_crypto.h
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,12 +475,19 @@ class Hash : public BaseObject {
475475

476476
Hash(Environment* env, v8::Local<v8::Object> wrap)
477477
: BaseObject(env, wrap),
478-
mdctx_(nullptr) {
478+
mdctx_(nullptr),
479+
md_len_(0) {
479480
MakeWeak();
480481
}
481482

483+
~Hash() override {
484+
OPENSSL_cleanse(md_value_, md_len_);
485+
}
486+
482487
private:
483488
EVPMDPointer mdctx_;
489+
unsigned char md_value_[EVP_MAX_MD_SIZE];
490+
unsigned int md_len_;
484491
};
485492

486493
class SignBase : public BaseObject {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.