diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2019-10-10 01:33:15 +0300 |
---|---|---|
committer | Myles Borins <myles.borins@gmail.com> | 2019-10-23 16:56:19 +0300 |
commit | 1d03df4c5e72c353ca36a44c0fb305ac62fee003 (patch) | |
tree | 0323bc3f5b21c9ef3c938c7b2eb1e83d3b85f6b7 /src/node_crypto.cc | |
parent | a1c524d734c653309d5451e2841285bd22ac49ba (diff) |
crypto: add Hash.prototype.copy() method
Make it possible to clone the internal state of a Hash object
into a new Hash object, i.e., to fork the state of the object.
Fixes: https://github.com/nodejs/node/issues/29903
PR-URL: https://github.com/nodejs/node/pull/29910
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src/node_crypto.cc')
-rw-r--r-- | src/node_crypto.cc | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/src/node_crypto.cc b/src/node_crypto.cc index d2563c0fb53..adefb7f482a 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -4720,7 +4720,16 @@ void Hash::Initialize(Environment* env, Local<Object> target) { void Hash::New(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - const node::Utf8Value hash_type(env->isolate(), args[0]); + const Hash* orig = nullptr; + const EVP_MD* md = nullptr; + + if (args[0]->IsObject()) { + ASSIGN_OR_RETURN_UNWRAP(&orig, args[0].As<Object>()); + md = EVP_MD_CTX_md(orig->mdctx_.get()); + } else { + const node::Utf8Value hash_type(env->isolate(), args[0]); + md = EVP_get_digestbyname(*hash_type); + } Maybe<unsigned int> xof_md_len = Nothing<unsigned int>(); if (!args[1]->IsUndefined()) { @@ -4729,17 +4738,19 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) { } Hash* hash = new Hash(env, args.This()); - if (!hash->HashInit(*hash_type, xof_md_len)) { + if (md == nullptr || !hash->HashInit(md, xof_md_len)) { return ThrowCryptoError(env, ERR_get_error(), "Digest method not supported"); } + + if (orig != nullptr && + 0 >= EVP_MD_CTX_copy(hash->mdctx_.get(), orig->mdctx_.get())) { + return ThrowCryptoError(env, ERR_get_error(), "Digest copy error"); + } } -bool Hash::HashInit(const char* hash_type, Maybe<unsigned int> xof_md_len) { - const EVP_MD* md = EVP_get_digestbyname(hash_type); - if (md == nullptr) - return false; +bool Hash::HashInit(const EVP_MD* md, Maybe<unsigned int> xof_md_len) { mdctx_.reset(EVP_MD_CTX_new()); if (!mdctx_ || EVP_DigestInit_ex(mdctx_.get(), md, nullptr) <= 0) { mdctx_.reset(); |