Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.

Commit 0a0e539

Browse files
author
Face Kapow
committed
make randombytes use runtime.random.getRandomValues (if available)
1 parent 547f7d9 commit 0a0e539

4 files changed

Lines changed: 86 additions & 7 deletions

File tree

js/core/libsodium.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,16 @@ module.exports = {
133133
throw new Error('crypto_aead_chacha20poly1305_decrypt: error decrypting box.');
134134
}
135135
return hexToU8(decipher.deciphertext);
136-
},
136+
}
137137
};
138138

139139
var justConvertHex = [
140+
{
141+
funcName: 'randombytes_buf',
142+
errorInfo: 'error generating randomness.',
143+
dataVerifier: isNumber,
144+
argName: 'buffer length'
145+
},
140146
{
141147
funcName: 'crypto_generichash',
142148
errorInfo: 'error calculating hash.'
@@ -153,10 +159,11 @@ var justConvertHex = [
153159

154160
for (var i = 0; i < justConvertHex.length; i++) {
155161
(function(i) {
156-
module.exports[justConvertHex[i].funcName] = function(data) {
157-
var result = lib[justConvertHex[i].funcName](stringOrU8(data, justConvertHex[i].funcName, 'data', 0));
162+
var f = justConvertHex[i];
163+
module.exports[f.funcName] = function(data) {
164+
var result = lib[f.funcName]((f.dataVerifier ? f.dataVerifier : stringOrU8)(data, f.funcName, (f.argName ? f.argName : 'data'), 0));
158165
if (!result) {
159-
throw new Error(justConvertHex[i].funcName + ': ' + justConvertHex[i].errorInfo);
166+
throw new Error(f.funcName + ': ' + (f.errorInfo ? f.errorInfo : 'unknown error.'));
160167
}
161168
return hexToU8(result);
162169
}

src/kernel/kernel-main.cc

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,60 @@ void KernelMain::MakeV8Snapshot() {
141141
}
142142

143143
const char* runtime_rng_name() {
144-
return "runtimejs";
144+
return "runtimejs";
145145
}
146146

147147
uint32_t runtime_rng_random() {
148+
// prevent abort()
149+
if (GLOBAL_engines()) {
150+
v8::Isolate* iv8 = GLOBAL_engines()->cpu_engine()->thread_manager()->current_thread()->IsolateV8();
151+
v8::Local<v8::Context> context = iv8->GetCurrentContext();
152+
153+
v8::Local<v8::Object> global = context->Global();
154+
v8::Local<v8::Object> runtimeObj = global->Get(context, v8::String::NewFromUtf8(iv8, "runtime", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()->ToObject();
155+
v8::Local<v8::Object> runtimeRandomObj = runtimeObj->Get(context, v8::String::NewFromUtf8(iv8, "random", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()->ToObject();
156+
v8::Local<v8::Function> runtimeRandomGetRandomValuesFunc = v8::Local<v8::Function>::Cast(runtimeRandomObj->Get(context, v8::String::NewFromUtf8(iv8, "getRandomValues", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked());
157+
158+
v8::Local<v8::Value> args[1] = { v8::Number::New(iv8, 1) };
159+
160+
// js equivalent: runtime.random.getRandomValues.apply(undefined, [1])
161+
v8::Local<v8::Object> u8Array = runtimeRandomGetRandomValuesFunc->Call(context, v8::Undefined(iv8), 1, args).ToLocalChecked()->ToObject(context).ToLocalChecked();
162+
return (uint8_t)(u8Array->Get(0)->ToNumber()->Value());
163+
} else {
164+
// mainly when libsodium is intialized, which is before V8 is available
165+
printf("[randombytes] fallback used\n");
148166
return 42;
167+
}
149168
}
150169

151170
void runtime_rng_buf(void* const buf, const size_t size) {
152-
uint8_t* b = reinterpret_cast<uint8_t*>(buf);
171+
uint8_t* b = reinterpret_cast<uint8_t*>(buf);
172+
173+
// prevent abort()
174+
if (GLOBAL_engines()) {
175+
v8::Isolate* iv8 = GLOBAL_engines()->cpu_engine()->thread_manager()->current_thread()->IsolateV8();
176+
v8::Local<v8::Context> context = iv8->GetCurrentContext();
177+
178+
v8::Local<v8::Object> global = context->Global();
179+
v8::Local<v8::Object> runtimeObj = global->Get(context, v8::String::NewFromUtf8(iv8, "runtime", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()->ToObject();
180+
v8::Local<v8::Object> runtimeRandomObj = runtimeObj->Get(context, v8::String::NewFromUtf8(iv8, "random", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked()->ToObject();
181+
v8::Local<v8::Function> runtimeRandomGetRandomValuesFunc = v8::Local<v8::Function>::Cast(runtimeRandomObj->Get(context, v8::String::NewFromUtf8(iv8, "getRandomValues", v8::NewStringType::kNormal).ToLocalChecked()).ToLocalChecked());
182+
183+
v8::Local<v8::Value> args[1] = { v8::Number::New(iv8, size) };
184+
185+
// js equivalent: runtime.random.getRandomValues.apply(undefined, [size])
186+
v8::Local<v8::Object> u8Array = runtimeRandomGetRandomValuesFunc->Call(context, v8::Undefined(iv8), 1, args).ToLocalChecked()->ToObject(context).ToLocalChecked();
187+
153188
for (size_t i = 0; i < size; ++i) {
154-
b[i] = 42;
189+
b[i] = (uint8_t)u8Array->Get(i)->ToNumber()->Value();
155190
}
191+
} else {
192+
// mainly when libsodium is intialized, which is before V8 is available
193+
printf("[randombytes] fallback used\n");
194+
for (size_t i = 0; i < size; ++i) {
195+
b[i] = 42;
196+
}
197+
}
156198
}
157199

158200
void KernelMain::InitSystemBSP(void* mbt) {

src/kernel/native-object.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,34 @@ NATIVE_FUNCTION(NativesObject, AllocDMA) {
11311131
args.GetReturnValue().Set(ret);
11321132
}
11331133

1134+
NATIVE_FUNCTION(LibsodiumObject, RandombytesBuf) {
1135+
PROLOGUE;
1136+
USEARG(0);
1137+
VALIDATEARG(0, NUMBER, "randombytes_buf: argument 0 is not a number.");
1138+
1139+
v8::Local<v8::Number> bufNum = arg0->ToNumber(context).ToLocalChecked();
1140+
unsigned long long bufLen = bufNum->Value();
1141+
1142+
unsigned char buf[bufLen];
1143+
randombytes_buf(buf, bufLen);
1144+
1145+
char returnString[(sizeof(buf)/sizeof(unsigned char))*2 + 1];
1146+
1147+
for (int i = 0; i < (sizeof(buf)/sizeof(unsigned char)); i++) {
1148+
sprintf(&returnString[i*2], "%02X", buf[i]);
1149+
}
1150+
1151+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1152+
1153+
v8::Local<v8::String> ret;
1154+
if (!maybe_ret.ToLocal(&ret)) {
1155+
args.GetReturnValue().SetUndefined();
1156+
return;
1157+
}
1158+
1159+
args.GetReturnValue().Set(ret);
1160+
}
1161+
11341162
NATIVE_FUNCTION(LibsodiumObject, BlakeHash) {
11351163
PROLOGUE;
11361164
USEARG(0);

src/kernel/native-object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,10 @@ class LibsodiumObject : public JsObjectWrapper<LibsodiumObject, NativeTypeId::TY
296296
DECLARE_NATIVE(AuthVerify);
297297
DECLARE_NATIVE(AEADChaCha20Poly135Encrypt);
298298
DECLARE_NATIVE(AEADChaCha20Poly135Decrypt);
299+
DECLARE_NATIVE(RandombytesBuf);
299300

300301
void ObjectInit(ExportBuilder obj) {
302+
obj.SetCallback("randombytes_buf", RandombytesBuf);
301303
obj.SetCallback("crypto_generichash", BlakeHash);
302304
obj.SetCallback("crypto_hash_sha256", Sha256Hash);
303305
obj.SetCallback("crypto_hash_sha512", Sha512Hash);

0 commit comments

Comments
 (0)