@@ -82,7 +82,6 @@ using v8::NewStringType;
82
82
using v8::Nothing;
83
83
using v8::Null;
84
84
using v8::Object;
85
- using v8::ObjectTemplate;
86
85
using v8::PropertyAttribute;
87
86
using v8::ReadOnly;
88
87
using v8::Signature;
@@ -4589,208 +4588,50 @@ inline void CopyBuffer(Local<Value> buf, std::vector<char>* vec) {
4589
4588
}
4590
4589
4591
4590
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;
4621
4596
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 >()) {}
4629
4599
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 ();
4635
4604
}
4636
4605
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);
4639
4609
}
4640
4610
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);
4643
4614
}
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_;
4655
4615
};
4656
4616
4657
4617
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
-
4731
4618
void 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.
4732
4627
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 ());
4794
4635
}
4795
4636
4796
4637
@@ -5355,7 +5196,6 @@ void Initialize(Local<Object> target,
5355
5196
5356
5197
env->SetMethod (target, " pbkdf2" , PBKDF2);
5357
5198
env->SetMethod (target, " randomBytes" , RandomBytes);
5358
- env->SetMethod (target, " randomFill" , RandomBytesBuffer);
5359
5199
env->SetMethod (target, " timingSafeEqual" , TimingSafeEqual);
5360
5200
env->SetMethod (target, " getSSLCiphers" , GetSSLCiphers);
5361
5201
env->SetMethod (target, " getCiphers" , GetCiphers);
@@ -5380,13 +5220,6 @@ void Initialize(Local<Object> target,
5380
5220
#ifndef OPENSSL_NO_SCRYPT
5381
5221
env->SetMethod (target, " scrypt" , Scrypt);
5382
5222
#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);
5390
5223
}
5391
5224
5392
5225
} // namespace crypto
0 commit comments