1 #include <assert.h>
2 #include <node.h>
3 #include <openssl/md5.h>
4 #include <openssl/rand.h>
5 #include <openssl/ssl.h>
6 
7 namespace {
8 
RandomBytes(const v8::FunctionCallbackInfo<v8::Value>& info)9 inline void RandomBytes(const v8::FunctionCallbackInfo<v8::Value>& info) {
10   assert(info[0]->IsArrayBufferView());
11   auto view = info[0].As<v8::ArrayBufferView>();
12   auto byte_offset = view->ByteOffset();
13   auto byte_length = view->ByteLength();
14   assert(view->HasBuffer());
15   auto buffer = view->Buffer();
16   auto contents = buffer->GetBackingStore();
17   auto data = static_cast<unsigned char*>(contents->Data()) + byte_offset;
18   assert(RAND_poll());
19   auto rval = RAND_bytes(data, static_cast<int>(byte_length));
20   info.GetReturnValue().Set(rval > 0);
21 }
22 
Hash(const v8::FunctionCallbackInfo<v8::Value>& info)23 inline void Hash(const v8::FunctionCallbackInfo<v8::Value>& info) {
24   assert(info[0]->IsArrayBufferView());
25   auto view = info[0].As<v8::ArrayBufferView>();
26   auto byte_offset = view->ByteOffset();
27   auto len = view->ByteLength();
28   assert(view->HasBuffer());
29   auto buffer = view->Buffer();
30   auto contents = buffer->GetBackingStore();
31   auto data = static_cast<unsigned char*>(contents->Data()) + byte_offset;
32   unsigned char md[MD5_DIGEST_LENGTH];
33   MD5_CTX c;
34   auto rval = MD5_Init(&c) && MD5_Update(&c, data, len) && MD5_Final(md, &c);
35   info.GetReturnValue().Set(rval > 0);
36 }
37 
Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> module, v8::Local<v8::Context> context)38 inline void Initialize(v8::Local<v8::Object> exports,
39                        v8::Local<v8::Value> module,
40                        v8::Local<v8::Context> context) {
41   auto isolate = context->GetIsolate();
42   auto key = v8::String::NewFromUtf8(
43       isolate, "randomBytes").ToLocalChecked();
44   auto value = v8::FunctionTemplate::New(isolate, RandomBytes)
45                    ->GetFunction(context)
46                    .ToLocalChecked();
47   assert(exports->Set(context, key, value).IsJust());
48 
49   const SSL_METHOD* method = TLSv1_2_server_method();
50   assert(method != nullptr);
51 
52   key = v8::String::NewFromUtf8(isolate, "hash").ToLocalChecked();
53   value = v8::FunctionTemplate::New(isolate, Hash)
54               ->GetFunction(context)
55               .ToLocalChecked();
56   assert(exports->Set(context, key, value).IsJust());
57 }
58 
59 }  // anonymous namespace
60 
61 NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize)
62