@@ -82,7 +82,6 @@ using v8::NewStringType;
8282using v8::Nothing;
8383using v8::Null;
8484using v8::Object;
85- using v8::ObjectTemplate;
8685using v8::PropertyAttribute;
8786using v8::ReadOnly;
8887using v8::Signature;
@@ -4589,208 +4588,50 @@ inline void CopyBuffer(Local<Value> buf, std::vector<char>* vec) {
45894588}
45904589
45914590
4592- // Only instantiate within a valid HandleScope.
4593- class RandomBytesRequest : public AsyncWrap , public ThreadPoolWork {
4594- public:
4595- enum FreeMode { FREE_DATA, DONT_FREE_DATA };
4596-
4597- RandomBytesRequest (Environment* env,
4598- Local<Object> object,
4599- size_t size,
4600- char * data,
4601- FreeMode free_mode)
4602- : AsyncWrap(env, object, AsyncWrap::PROVIDER_RANDOMBYTESREQUEST),
4603- ThreadPoolWork (env),
4604- error_(0 ),
4605- size_(size),
4606- data_(data),
4607- free_mode_(free_mode) {
4608- }
4609-
4610- inline size_t size () const {
4611- return size_;
4612- }
4613-
4614- inline char * data () const {
4615- return data_;
4616- }
4617-
4618- inline void set_data (char * data) {
4619- data_ = data;
4620- }
4591+ struct RandomBytesJob : public CryptoJob {
4592+ unsigned char * data;
4593+ size_t size;
4594+ CryptoErrorVector errors;
4595+ Maybe<int > rc;
46214596
4622- inline void release () {
4623- size_ = 0 ;
4624- if (free_mode_ == FREE_DATA) {
4625- free (data_);
4626- data_ = nullptr ;
4627- }
4628- }
4597+ inline explicit RandomBytesJob (Environment* env)
4598+ : CryptoJob(env), rc(Nothing<int >()) {}
46294599
4630- inline void return_memory (char ** d, size_t * len) {
4631- *d = data_;
4632- data_ = nullptr ;
4633- *len = size_;
4634- size_ = 0 ;
4600+ inline void DoThreadPoolWork () override {
4601+ CheckEntropy (); // Ensure that OpenSSL's PRNG is properly seeded.
4602+ rc = Just (RAND_bytes (data, size));
4603+ if (0 == rc.FromJust ()) errors.Capture ();
46354604 }
46364605
4637- inline unsigned long error () const { // NOLINT(runtime/int)
4638- return error_;
4606+ inline void AfterThreadPoolWork () override {
4607+ Local<Value> arg = ToResult ();
4608+ async_wrap->MakeCallback (env->ondone_string (), 1 , &arg);
46394609 }
46404610
4641- inline void set_error (unsigned long err) { // NOLINT(runtime/int)
4642- error_ = err;
4611+ inline Local<Value> ToResult () const {
4612+ if (errors.empty ()) return Undefined (env->isolate ());
4613+ return errors.ToException (env);
46434614 }
4644-
4645- size_t self_size () const override { return sizeof (*this ); }
4646-
4647- void DoThreadPoolWork () override ;
4648- void AfterThreadPoolWork (int status) override ;
4649-
4650- private:
4651- unsigned long error_; // NOLINT(runtime/int)
4652- size_t size_;
4653- char * data_;
4654- const FreeMode free_mode_;
46554615};
46564616
46574617
4658- void RandomBytesRequest::DoThreadPoolWork () {
4659- // Ensure that OpenSSL's PRNG is properly seeded.
4660- CheckEntropy ();
4661-
4662- const int r = RAND_bytes (reinterpret_cast <unsigned char *>(data_), size_);
4663-
4664- // RAND_bytes() returns 0 on error.
4665- if (r == 0 ) {
4666- set_error (ERR_get_error ()); // NOLINT(runtime/int)
4667- } else if (r == -1 ) {
4668- set_error (static_cast <unsigned long >(-1 )); // NOLINT(runtime/int)
4669- }
4670- }
4671-
4672-
4673- // don't call this function without a valid HandleScope
4674- void RandomBytesCheck (RandomBytesRequest* req, Local<Value> (*argv)[2]) {
4675- if (req->error ()) {
4676- char errmsg[256 ] = " Operation not supported" ;
4677-
4678- if (req->error () != static_cast <unsigned long >(-1 )) // NOLINT(runtime/int)
4679- ERR_error_string_n (req->error (), errmsg, sizeof errmsg);
4680-
4681- (*argv)[0 ] = Exception::Error (OneByteString (req->env ()->isolate (), errmsg));
4682- (*argv)[1 ] = Null (req->env ()->isolate ());
4683- req->release ();
4684- } else {
4685- char * data = nullptr ;
4686- size_t size;
4687- req->return_memory (&data, &size);
4688- (*argv)[0 ] = Null (req->env ()->isolate ());
4689- Local<Value> buffer =
4690- req->object ()->Get (req->env ()->context (),
4691- req->env ()->buffer_string ()).ToLocalChecked ();
4692-
4693- if (buffer->IsArrayBufferView ()) {
4694- CHECK_LE (req->size (), Buffer::Length (buffer));
4695- char * buf = Buffer::Data (buffer);
4696- memcpy (buf, data, req->size ());
4697- (*argv)[1 ] = buffer;
4698- } else {
4699- (*argv)[1 ] = Buffer::New (req->env (), data, size)
4700- .ToLocalChecked ();
4701- }
4702- }
4703- }
4704-
4705-
4706- void RandomBytesRequest::AfterThreadPoolWork (int status) {
4707- std::unique_ptr<RandomBytesRequest> req (this );
4708- if (status == UV_ECANCELED)
4709- return ;
4710- CHECK_EQ (status, 0 );
4711- HandleScope handle_scope (env ()->isolate ());
4712- Context::Scope context_scope (env ()->context ());
4713- Local<Value> argv[2 ];
4714- RandomBytesCheck (this , &argv);
4715- MakeCallback (env ()->ondone_string (), arraysize (argv), argv);
4716- }
4717-
4718-
4719- void RandomBytesProcessSync (Environment* env,
4720- std::unique_ptr<RandomBytesRequest> req,
4721- Local<Value> (*argv)[2]) {
4722- env->PrintSyncTrace ();
4723- req->DoThreadPoolWork ();
4724- RandomBytesCheck (req.get (), argv);
4725-
4726- if (!(*argv)[0 ]->IsNull ())
4727- env->isolate ()->ThrowException ((*argv)[0 ]);
4728- }
4729-
4730-
47314618void RandomBytes (const FunctionCallbackInfo<Value>& args) {
4619+ CHECK (args[0 ]->IsArrayBufferView ()); // buffer; wrap object retains ref.
4620+ CHECK (args[1 ]->IsUint32 ()); // offset
4621+ CHECK (args[2 ]->IsUint32 ()); // size
4622+ CHECK (args[3 ]->IsObject () || args[3 ]->IsUndefined ()); // wrap object
4623+ const uint32_t offset = args[1 ].As <Uint32>()->Value ();
4624+ const uint32_t size = args[2 ].As <Uint32>()->Value ();
4625+ CHECK_GE (offset + size, offset); // Overflow check.
4626+ CHECK_LE (offset + size, Buffer::Length (args[0 ])); // Bounds check.
47324627 Environment* env = Environment::GetCurrent (args);
4733-
4734- const int64_t size = args[0 ]->IntegerValue ();
4735- CHECK (size <= Buffer::kMaxLength );
4736-
4737- Local<Object> obj = env->randombytes_constructor_template ()->
4738- NewInstance (env->context ()).ToLocalChecked ();
4739- char * data = node::Malloc (size);
4740- std::unique_ptr<RandomBytesRequest> req (
4741- new RandomBytesRequest (env,
4742- obj,
4743- size,
4744- data,
4745- RandomBytesRequest::FREE_DATA));
4746-
4747- if (args[1 ]->IsFunction ()) {
4748- obj->Set (env->context (), env->ondone_string (), args[1 ]).FromJust ();
4749-
4750- req.release ()->ScheduleWork ();
4751- args.GetReturnValue ().Set (obj);
4752- } else {
4753- Local<Value> argv[2 ];
4754- RandomBytesProcessSync (env, std::move (req), &argv);
4755- if (argv[0 ]->IsNull ())
4756- args.GetReturnValue ().Set (argv[1 ]);
4757- }
4758- }
4759-
4760-
4761- void RandomBytesBuffer (const FunctionCallbackInfo<Value>& args) {
4762- Environment* env = Environment::GetCurrent (args);
4763-
4764- CHECK (args[0 ]->IsArrayBufferView ());
4765- CHECK (args[1 ]->IsUint32 ());
4766- CHECK (args[2 ]->IsUint32 ());
4767-
4768- int64_t offset = args[1 ]->IntegerValue ();
4769- int64_t size = args[2 ]->IntegerValue ();
4770-
4771- Local<Object> obj = env->randombytes_constructor_template ()->
4772- NewInstance (env->context ()).ToLocalChecked ();
4773- obj->Set (env->context (), env->buffer_string (), args[0 ]).FromJust ();
4774- char * data = Buffer::Data (args[0 ]);
4775- data += offset;
4776-
4777- std::unique_ptr<RandomBytesRequest> req (
4778- new RandomBytesRequest (env,
4779- obj,
4780- size,
4781- data,
4782- RandomBytesRequest::DONT_FREE_DATA));
4783- if (args[3 ]->IsFunction ()) {
4784- obj->Set (env->context (), env->ondone_string (), args[3 ]).FromJust ();
4785-
4786- req.release ()->ScheduleWork ();
4787- args.GetReturnValue ().Set (obj);
4788- } else {
4789- Local<Value> argv[2 ];
4790- RandomBytesProcessSync (env, std::move (req), &argv);
4791- if (argv[0 ]->IsNull ())
4792- args.GetReturnValue ().Set (argv[1 ]);
4793- }
4628+ std::unique_ptr<RandomBytesJob> job (new RandomBytesJob (env));
4629+ job->data = reinterpret_cast <unsigned char *>(Buffer::Data (args[0 ])) + offset;
4630+ job->size = size;
4631+ if (args[3 ]->IsObject ()) return RandomBytesJob::Run (std::move (job), args[3 ]);
4632+ env->PrintSyncTrace ();
4633+ job->DoThreadPoolWork ();
4634+ args.GetReturnValue ().Set (job->ToResult ());
47944635}
47954636
47964637
@@ -5355,7 +5196,6 @@ void Initialize(Local<Object> target,
53555196
53565197 env->SetMethod (target, " pbkdf2" , PBKDF2);
53575198 env->SetMethod (target, " randomBytes" , RandomBytes);
5358- env->SetMethod (target, " randomFill" , RandomBytesBuffer);
53595199 env->SetMethod (target, " timingSafeEqual" , TimingSafeEqual);
53605200 env->SetMethod (target, " getSSLCiphers" , GetSSLCiphers);
53615201 env->SetMethod (target, " getCiphers" , GetCiphers);
@@ -5380,13 +5220,6 @@ void Initialize(Local<Object> target,
53805220#ifndef OPENSSL_NO_SCRYPT
53815221 env->SetMethod (target, " scrypt" , Scrypt);
53825222#endif // OPENSSL_NO_SCRYPT
5383-
5384- Local<FunctionTemplate> rb = FunctionTemplate::New (env->isolate ());
5385- rb->SetClassName (FIXED_ONE_BYTE_STRING (env->isolate (), " RandomBytes" ));
5386- AsyncWrap::AddWrapMethods (env, rb);
5387- Local<ObjectTemplate> rbt = rb->InstanceTemplate ();
5388- rbt->SetInternalFieldCount (1 );
5389- env->set_randombytes_constructor_template (rbt);
53905223}
53915224
53925225} // namespace crypto
0 commit comments