@@ -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