1212namespace node {
1313
1414using v8::Array;
15+ using v8::ArrayBuffer;
16+ using v8::BackingStore;
1517using v8::FunctionCallbackInfo;
1618using v8::FunctionTemplate;
1719using v8::HandleScope;
1820using v8::Int32;
21+ using v8::Isolate;
1922using v8::Local;
2023using v8::Object;
2124using v8::Uint32;
@@ -720,7 +723,9 @@ void CipherBase::SetAAD(const FunctionCallbackInfo<Value>& args) {
720723CipherBase::UpdateResult CipherBase::Update (
721724 const char * data,
722725 size_t len,
723- AllocatedBuffer* out) {
726+ std::unique_ptr<BackingStore>* out) {
727+ Environment* env = this ->env ();
728+ Isolate* isolate = env->isolate ();
724729 if (!ctx_ || len > INT_MAX)
725730 return kErrorState ;
726731 MarkPopErrorOnReturn mark_pop_error_on_return;
@@ -747,15 +752,22 @@ CipherBase::UpdateResult CipherBase::Update(
747752 return kErrorState ;
748753 }
749754
750- *out = AllocatedBuffer::AllocateManaged (env (), buf_len);
755+ {
756+ NoArrayBufferZeroFillScope no_zero_fill_scope (env->isolate_data ());
757+ *out = ArrayBuffer::NewBackingStore (isolate, buf_len);
758+ }
759+
751760 int r = EVP_CipherUpdate (ctx_.get (),
752- reinterpret_cast <unsigned char *>(out-> data ()),
761+ static_cast <unsigned char *>((* out)-> Data ()),
753762 &buf_len,
754763 reinterpret_cast <const unsigned char *>(data),
755764 len);
756765
757- CHECK_LE (static_cast <size_t >(buf_len), out->size ());
758- out->Resize (buf_len);
766+ CHECK_LE (static_cast <size_t >(buf_len), (*out)->ByteLength ());
767+ if (buf_len == 0 )
768+ *out = ArrayBuffer::NewBackingStore (isolate, 0 );
769+ else
770+ *out = BackingStore::Reallocate (isolate, std::move (*out), buf_len);
759771
760772 // When in CCM mode, EVP_CipherUpdate will fail if the authentication tag is
761773 // invalid. In that case, remember the error and throw in final().
@@ -770,7 +782,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
770782 Decode<CipherBase>(args, [](CipherBase* cipher,
771783 const FunctionCallbackInfo<Value>& args,
772784 const char * data, size_t size) {
773- AllocatedBuffer out;
785+ std::unique_ptr<BackingStore> out;
774786 Environment* env = Environment::GetCurrent (args);
775787
776788 if (UNLIKELY (size > INT_MAX))
@@ -786,8 +798,9 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
786798 return ;
787799 }
788800
789- CHECK (out.data () != nullptr || out.size () == 0 );
790- args.GetReturnValue ().Set (out.ToBuffer ().FromMaybe (Local<Value>()));
801+ Local<ArrayBuffer> ab = ArrayBuffer::New (env->isolate (), std::move (out));
802+ args.GetReturnValue ().Set (
803+ Buffer::New (env, ab, 0 , ab->ByteLength ()).FromMaybe (Local<Value>()));
791804 });
792805}
793806
@@ -806,36 +819,40 @@ void CipherBase::SetAutoPadding(const FunctionCallbackInfo<Value>& args) {
806819 args.GetReturnValue ().Set (b); // Possibly report invalid state failure
807820}
808821
809- bool CipherBase::Final (AllocatedBuffer* out) {
822+ bool CipherBase::Final (std::unique_ptr<BackingStore>* out) {
823+ Environment* env = this ->env ();
824+ Isolate* isolate = env->isolate ();
810825 if (!ctx_)
811826 return false ;
812827
813828 const int mode = EVP_CIPHER_CTX_mode (ctx_.get ());
814829
815- *out = AllocatedBuffer::AllocateManaged (
816- env (),
817- static_cast <size_t >(EVP_CIPHER_CTX_block_size (ctx_.get ())));
830+ {
831+ NoArrayBufferZeroFillScope no_zero_fill_scope (env->isolate_data ());
832+ *out = ArrayBuffer::NewBackingStore (isolate,
833+ static_cast <size_t >(EVP_CIPHER_CTX_block_size (ctx_.get ())));
834+ }
818835
819- if (kind_ == kDecipher && IsSupportedAuthenticatedMode (ctx_.get ())) {
836+ if (kind_ == kDecipher && IsSupportedAuthenticatedMode (ctx_.get ()))
820837 MaybePassAuthTagToOpenSSL ();
821- }
822838
823839 // In CCM mode, final() only checks whether authentication failed in update().
824840 // EVP_CipherFinal_ex must not be called and will fail.
825841 bool ok;
826842 if (kind_ == kDecipher && mode == EVP_CIPH_CCM_MODE) {
827843 ok = !pending_auth_failed_;
828- *out = AllocatedBuffer::AllocateManaged ( env () , 0 ); // Empty buffer.
844+ *out = ArrayBuffer::NewBackingStore (isolate , 0 );
829845 } else {
830- int out_len = out-> size ();
846+ int out_len = (* out)-> ByteLength ();
831847 ok = EVP_CipherFinal_ex (ctx_.get (),
832- reinterpret_cast <unsigned char *>(out-> data ()),
848+ static_cast <unsigned char *>((* out)-> Data ()),
833849 &out_len) == 1 ;
834850
835- if (out_len >= 0 )
836- out->Resize (out_len);
851+ CHECK_LE (static_cast <size_t >(out_len), (*out)->ByteLength ());
852+ if (out_len > 0 )
853+ *out = BackingStore::Reallocate (isolate, std::move (*out), out_len);
837854 else
838- *out = AllocatedBuffer (); // *out will not be used.
855+ *out = ArrayBuffer::NewBackingStore (isolate, 0 );
839856
840857 if (ok && kind_ == kCipher && IsAuthenticatedMode ()) {
841858 // In GCM mode, the authentication tag length can be specified in advance,
@@ -864,7 +881,7 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
864881 if (cipher->ctx_ == nullptr )
865882 return THROW_ERR_CRYPTO_INVALID_STATE (env);
866883
867- AllocatedBuffer out;
884+ std::unique_ptr<BackingStore> out;
868885
869886 // Check IsAuthenticatedMode() first, Final() destroys the EVP_CIPHER_CTX.
870887 const bool is_auth_mode = cipher->IsAuthenticatedMode ();
@@ -878,7 +895,9 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
878895 return ThrowCryptoError (env, ERR_get_error (), msg);
879896 }
880897
881- args.GetReturnValue ().Set (out.ToBuffer ().FromMaybe (Local<Value>()));
898+ Local<ArrayBuffer> ab = ArrayBuffer::New (env->isolate (), std::move (out));
899+ args.GetReturnValue ().Set (
900+ Buffer::New (env, ab, 0 , ab->ByteLength ()).FromMaybe (Local<Value>()));
882901}
883902
884903template <PublicKeyCipher::Operation operation,
@@ -891,7 +910,8 @@ bool PublicKeyCipher::Cipher(
891910 const EVP_MD* digest,
892911 const ArrayBufferOrViewContents<unsigned char >& oaep_label,
893912 const ArrayBufferOrViewContents<unsigned char >& data,
894- AllocatedBuffer* out) {
913+ std::unique_ptr<BackingStore>* out) {
914+ Isolate* isolate = env->isolate ();
895915 EVPKeyCtxPointer ctx (EVP_PKEY_CTX_new (pkey.get (), nullptr ));
896916 if (!ctx)
897917 return false ;
@@ -927,18 +947,26 @@ bool PublicKeyCipher::Cipher(
927947 return false ;
928948 }
929949
930- *out = AllocatedBuffer::AllocateManaged (env, out_len);
950+ {
951+ NoArrayBufferZeroFillScope no_zero_fill_scope (env->isolate_data ());
952+ *out = ArrayBuffer::NewBackingStore (isolate, out_len);
953+ }
931954
932955 if (EVP_PKEY_cipher (
933956 ctx.get (),
934- reinterpret_cast <unsigned char *>(out-> data ()),
957+ static_cast <unsigned char *>((* out)-> Data ()),
935958 &out_len,
936959 data.data (),
937960 data.size ()) <= 0 ) {
938961 return false ;
939962 }
940963
941- out->Resize (out_len);
964+ CHECK_LE (out_len, (*out)->ByteLength ());
965+ if (out_len > 0 )
966+ *out = BackingStore::Reallocate (isolate, std::move (*out), out_len);
967+ else
968+ *out = ArrayBuffer::NewBackingStore (isolate, 0 );
969+
942970 return true ;
943971}
944972
@@ -977,15 +1005,15 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
9771005 return THROW_ERR_OUT_OF_RANGE (env, " oaep_label is too big" );
9781006 }
9791007
980- AllocatedBuffer out;
1008+ std::unique_ptr<BackingStore> out;
9811009 if (!Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
9821010 env, pkey, padding, digest, oaep_label, buf, &out)) {
9831011 return ThrowCryptoError (env, ERR_get_error ());
9841012 }
9851013
986- Local<Value> result ;
987- if (out. ToBuffer ().ToLocal (&result))
988- args. GetReturnValue (). Set (result );
1014+ Local<ArrayBuffer> ab = ArrayBuffer::New (env-> isolate (), std::move (out)) ;
1015+ args. GetReturnValue ().Set (
1016+ Buffer::New (env, ab, 0 , ab-> ByteLength ()). FromMaybe (Local<Value>()) );
9891017}
9901018
9911019} // namespace crypto
0 commit comments