@@ -24,17 +24,13 @@ using v8::Uint32;
24
24
using v8::Value;
25
25
26
26
namespace crypto {
27
- Hash::Hash (Environment* env, Local<Object> wrap)
28
- : BaseObject(env, wrap),
29
- mdctx_ (nullptr ),
30
- has_md_(false ),
31
- md_value_(nullptr ) {
27
+ Hash::Hash (Environment* env, Local<Object> wrap) : BaseObject(env, wrap) {
32
28
MakeWeak ();
33
29
}
34
30
35
31
void Hash::MemoryInfo (MemoryTracker* tracker) const {
36
32
tracker->TrackFieldWithSize (" mdctx" , mdctx_ ? kSizeOf_EVP_MD_CTX : 0 );
37
- tracker->TrackFieldWithSize (" md" , md_len_);
33
+ tracker->TrackFieldWithSize (" md" , digest_ ? md_len_ : 0 );
38
34
}
39
35
40
36
void Hash::GetHashes (const FunctionCallbackInfo<Value>& args) {
@@ -63,11 +59,6 @@ void Hash::Initialize(Environment* env, Local<Object> target) {
63
59
HashJob::Initialize (env, target);
64
60
}
65
61
66
- Hash::~Hash () {
67
- if (md_value_ != nullptr )
68
- OPENSSL_clear_free (md_value_, md_len_);
69
- }
70
-
71
62
void Hash::New (const FunctionCallbackInfo<Value>& args) {
72
63
Environment* env = Environment::GetCurrent (args);
73
64
@@ -150,47 +141,50 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
150
141
encoding = ParseEncoding (env->isolate (), args[0 ], BUFFER);
151
142
}
152
143
144
+ unsigned int len = hash->md_len_ ;
145
+
153
146
// TODO(tniessen): SHA3_squeeze does not work for zero-length outputs on all
154
147
// platforms and will cause a segmentation fault if called. This workaround
155
148
// causes hash.digest() to correctly return an empty buffer / string.
156
149
// See https://github.com/openssl/openssl/issues/9431.
157
- if (!hash->has_md_ && hash->md_len_ == 0 ) {
158
- hash->has_md_ = true ;
159
- }
160
150
161
- if (!hash->has_md_ ) {
151
+ if (!hash->digest_ && len > 0 ) {
162
152
// Some hash algorithms such as SHA3 do not support calling
163
153
// EVP_DigestFinal_ex more than once, however, Hash._flush
164
154
// and Hash.digest can both be used to retrieve the digest,
165
155
// so we need to cache it.
166
156
// See https://github.com/nodejs/node/issues/28245.
167
157
168
- hash->md_value_ = MallocOpenSSL<unsigned char >(hash->md_len_ );
158
+ char * md_value = MallocOpenSSL<char >(len);
159
+ ByteSource digest = ByteSource::Allocated (md_value, len);
169
160
170
161
size_t default_len = EVP_MD_CTX_size (hash->mdctx_ .get ());
171
162
int ret;
172
- if (hash->md_len_ == default_len) {
173
- ret = EVP_DigestFinal_ex (hash->mdctx_ .get (), hash->md_value_ ,
174
- &hash->md_len_ );
163
+ if (len == default_len) {
164
+ ret = EVP_DigestFinal_ex (
165
+ hash->mdctx_ .get (),
166
+ reinterpret_cast <unsigned char *>(md_value),
167
+ &len);
168
+ // The output length should always equal hash->md_len_
169
+ CHECK_EQ (len, hash->md_len_ );
175
170
} else {
176
- ret = EVP_DigestFinalXOF (hash->mdctx_ .get (), hash->md_value_ ,
177
- hash->md_len_ );
171
+ ret = EVP_DigestFinalXOF (
172
+ hash->mdctx_ .get (),
173
+ reinterpret_cast <unsigned char *>(md_value),
174
+ len);
178
175
}
179
176
180
- if (ret != 1 ) {
181
- OPENSSL_free (hash->md_value_ );
182
- hash->md_value_ = nullptr ;
177
+ if (ret != 1 )
183
178
return ThrowCryptoError (env, ERR_get_error ());
184
- }
185
179
186
- hash->has_md_ = true ;
180
+ hash->digest_ = std::move (digest) ;
187
181
}
188
182
189
183
Local<Value> error;
190
184
MaybeLocal<Value> rc =
191
185
StringBytes::Encode (env->isolate (),
192
- reinterpret_cast < const char *>( hash->md_value_ ),
193
- hash-> md_len_ ,
186
+ hash->digest_ . get ( ),
187
+ len ,
194
188
encoding,
195
189
&error);
196
190
if (rc.IsEmpty ()) {
0 commit comments