From 47c2b678b7554bb08c9868c01508fea3456426b0 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 13 Feb 2020 12:05:18 +0100 Subject: [PATCH] src: DRY crypto Update() methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Factor out the common logic into a template function. Removes approximately six instances of copy/pasted code. PR-URL: https://github.com/nodejs/node/pull/31767 Reviewed-By: Santiago Gimeno Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: David Carlier Reviewed-By: Tobias Nießen --- src/node_crypto.cc | 169 +++++++++++++++------------------------------ 1 file changed, 56 insertions(+), 113 deletions(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 3a1ff9de476a68..e136903989ec51 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -145,6 +145,26 @@ template int SSLWrap::SelectALPNCallback( unsigned int inlen, void* arg); +template +void Decode(const FunctionCallbackInfo& args, + void (*callback)(T*, const FunctionCallbackInfo&, + const char*, size_t)) { + T* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); + + if (args[0]->IsString()) { + StringBytes::InlineDecoder decoder; + Environment* env = Environment::GetCurrent(args); + enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); + if (decoder.Decode(env, args[0].As(), enc).IsNothing()) + return; + callback(ctx, args, decoder.out(), decoder.size()); + } else { + ArrayBufferViewContents buf(args[0]); + callback(ctx, args, buf.data(), buf.length()); + } +} + static int PasswordCallback(char* buf, int size, int rwflag, void* u) { const char* passphrase = static_cast(u); if (passphrase != nullptr) { @@ -3946,38 +3966,24 @@ CipherBase::UpdateResult CipherBase::Update(const char* data, void CipherBase::Update(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - CipherBase* cipher; - ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); - - AllocatedBuffer out; - UpdateResult r; - - // Only copy the data if we have to, because it's a string - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); - - if (decoder.Decode(env, args[0].As(), enc).IsNothing()) + Decode(args, [](CipherBase* cipher, + const FunctionCallbackInfo& args, + const char* data, size_t size) { + AllocatedBuffer out; + UpdateResult r = cipher->Update(data, size, &out); + + if (r != kSuccess) { + if (r == kErrorState) { + Environment* env = Environment::GetCurrent(args); + ThrowCryptoError(env, ERR_get_error(), + "Trying to add data in unsupported state"); + } return; - r = cipher->Update(decoder.out(), decoder.size(), &out); - } else { - ArrayBufferViewContents buf(args[0]); - r = cipher->Update(buf.data(), buf.length(), &out); - } - - if (r != kSuccess) { - if (r == kErrorState) { - ThrowCryptoError(env, ERR_get_error(), - "Trying to add data in unsupported state"); } - return; - } - - CHECK(out.data() != nullptr || out.size() == 0); - args.GetReturnValue().Set(out.ToBuffer().ToLocalChecked()); + CHECK(out.data() != nullptr || out.size() == 0); + args.GetReturnValue().Set(out.ToBuffer().ToLocalChecked()); + }); } @@ -4139,26 +4145,11 @@ bool Hmac::HmacUpdate(const char* data, int len) { void Hmac::HmacUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Hmac* hmac; - ASSIGN_OR_RETURN_UNWRAP(&hmac, args.Holder()); - - // Only copy the data if we have to, because it's a string - bool r = false; - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); - - if (!decoder.Decode(env, args[0].As(), enc).IsNothing()) { - r = hmac->HmacUpdate(decoder.out(), decoder.size()); - } - } else { - ArrayBufferViewContents buf(args[0]); - r = hmac->HmacUpdate(buf.data(), buf.length()); - } - - args.GetReturnValue().Set(r); + Decode(args, [](Hmac* hmac, const FunctionCallbackInfo& args, + const char* data, size_t size) { + bool r = hmac->HmacUpdate(data, size); + args.GetReturnValue().Set(r); + }); } @@ -4287,28 +4278,11 @@ bool Hash::HashUpdate(const char* data, int len) { void Hash::HashUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Hash* hash; - ASSIGN_OR_RETURN_UNWRAP(&hash, args.Holder()); - - // Only copy the data if we have to, because it's a string - bool r = true; - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); - - if (decoder.Decode(env, args[0].As(), enc).IsNothing()) { - args.GetReturnValue().Set(false); - return; - } - r = hash->HashUpdate(decoder.out(), decoder.size()); - } else if (args[0]->IsArrayBufferView()) { - ArrayBufferViewContents buf(args[0].As()); - r = hash->HashUpdate(buf.data(), buf.length()); - } - - args.GetReturnValue().Set(r); + Decode(args, [](Hash* hash, const FunctionCallbackInfo& args, + const char* data, size_t size) { + bool r = hash->HashUpdate(data, size); + args.GetReturnValue().Set(r); + }); } @@ -4509,27 +4483,11 @@ void Sign::SignInit(const FunctionCallbackInfo& args) { void Sign::SignUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Sign* sign; - ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); - - Error err; - - // Only copy the data if we have to, because it's a string - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); - - if (decoder.Decode(env, args[0].As(), enc).IsNothing()) - return; - err = sign->Update(decoder.out(), decoder.size()); - } else { - ArrayBufferViewContents buf(args[0]); - err = sign->Update(buf.data(), buf.length()); - } - - sign->CheckThrow(err); + Decode(args, [](Sign* sign, const FunctionCallbackInfo& args, + const char* data, size_t size) { + Error err = sign->Update(data, size); + sign->CheckThrow(err); + }); } static int GetDefaultSignPadding(const ManagedEVPPKey& key) { @@ -4847,27 +4805,12 @@ void Verify::VerifyInit(const FunctionCallbackInfo& args) { void Verify::VerifyUpdate(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - - Verify* verify; - ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); - - Error err; - - // Only copy the data if we have to, because it's a string - if (args[0]->IsString()) { - StringBytes::InlineDecoder decoder; - enum encoding enc = ParseEncoding(env->isolate(), args[1], UTF8); - - if (decoder.Decode(env, args[0].As(), enc).IsNothing()) - return; - err = verify->Update(decoder.out(), decoder.size()); - } else { - ArrayBufferViewContents buf(args[0]); - err = verify->Update(buf.data(), buf.length()); - } - - verify->CheckThrow(err); + Decode(args, [](Verify* verify, + const FunctionCallbackInfo& args, + const char* data, size_t size) { + Error err = verify->Update(data, size); + verify->CheckThrow(err); + }); }