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

Commit a44b25a

Browse files
committed
Bind libsodium hash functions (except pwhash), bind libsodium secretbox
1 parent 25d6bcb commit a44b25a

6 files changed

Lines changed: 319 additions & 1 deletion

File tree

SConstruct

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ config = {
3535
'-Wno-unused',
3636
'-fno-exceptions',
3737
'-Wno-unused-parameter',
38-
'-fdiagnostics-color',
3938
'-D__runtime_js__',
4039
'-DRUNTIMEJS_PLATFORM_X64',
4140
]),

js/core/libsodium.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2014-2015 runtime.js project authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
'use strict';
16+
17+
var lib = require('./resources').libsodium;
18+
19+
// Helper function to convert hex results into Uint8Arrays.
20+
function hexToU8(hexStr) {
21+
var u8 = new Uint8Array(hexStr.length/2);
22+
for (var i = 0; i < (hexStr.length/2); i++) {
23+
u8[i] = parseInt(hexStr.substr(i*2, 2), 16);
24+
}
25+
return u8;
26+
}
27+
28+
module.exports = {
29+
crypto_secretbox_easy: function(data, key) {
30+
var nonce = runtime.random.getRandomValues(lib.crypto_constants().crypto_secretbox_NONCEBYTES);
31+
var nonceArr = new Array(lib.crypto_constants().crypto_secretbox_NONCEBYTES);
32+
for (var i = 0; i < nonce.length; i++) {
33+
nonceArr[i] = nonce[i];
34+
}
35+
36+
var cipher = lib.crypto_secretbox_easy(data, key, nonceArr);
37+
if (!cipher) {
38+
throw new Error('crypto_secretbox_easy: error creating box.');
39+
}
40+
return {
41+
ciphertext: hexToU8(cipher),
42+
nonce: nonce
43+
};
44+
},
45+
crypto_secretbox_open_easy: function(cipheru8, key, nonce) {
46+
var nonceArr = new Array(lib.crypto_constants().crypto_secretbox_NONCEBYTES);
47+
for (var i = 0; i < nonce.length; i++) {
48+
nonceArr[i] = nonce[i];
49+
}
50+
51+
var cipherArr = new Array(cipheru8.length);
52+
for (var i = 0; i < cipheru8.length; i++) {
53+
cipherArr[i] = cipheru8[i];
54+
}
55+
56+
var decipher = lib.crypto_secretbox_open_easy(cipherArr, key, nonceArr);
57+
if (!decipher) {
58+
throw new Error('crypto_secretbox_open_easy: error decrypting box.');
59+
}
60+
return hexToU8(decipher);
61+
}
62+
};
63+
64+
var justConvertHex = [
65+
{
66+
funcName: 'crypto_generichash',
67+
errorInfo: 'error calculating hash.'
68+
},
69+
{
70+
funcName: 'crypto_hash_sha256',
71+
errorInfo: 'error calculating hash.'
72+
},
73+
{
74+
funcName: 'crypto_hash_sha512',
75+
errorInfo: 'error calculating hash.'
76+
}
77+
];
78+
79+
for (var i = 0; i < justConvertHex.length; i++) {
80+
(function(i) {
81+
module.exports[justConvertHex[i].funcName] = function(data) {
82+
var result = lib[justConvertHex[i].funcName](data);
83+
if (!result) {
84+
throw new Error(justConvertHex[i].funcName + ': ' + justConvertHex[i].errprInfo);
85+
}
86+
return hexToU8(result);
87+
}
88+
})(i);
89+
}

js/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ runtime.shell.setCommand('reboot', function(args, env, cb) {
6060
cb(0);
6161
});
6262

63+
runtime.libsodium = require('./core/libsodium');
64+
6365

6466
// Start device drivers
6567
require('./driver/ps2');

src/kernel/native-object.cc

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <kernel/version.h>
2626
#include <kernel/heap-snapshot.h>
2727
#include <v8-profiler.h>
28+
#include <sodium.h>
2829

2930
namespace rt {
3031

@@ -572,6 +573,7 @@ NATIVE_FUNCTION(NativesObject, Resources) {
572573
LOCAL_V8STRING(s_allocator, "allocator");
573574
LOCAL_V8STRING(s_loader, "loader");
574575
LOCAL_V8STRING(s_natives, "natives");
576+
LOCAL_V8STRING(s_libsodium, "libsodium");
575577

576578
v8::Local<v8::Object> obj = v8::Object::New(iv8);
577579

@@ -601,6 +603,10 @@ NATIVE_FUNCTION(NativesObject, Resources) {
601603
->BindToTemplateCache(th->template_cache())
602604
->GetInstance());
603605

606+
obj->Set(context, s_libsodium, (new LibsodiumObject())
607+
->BindToTemplateCache(th->template_cache())
608+
->GetInstance());
609+
604610
args.GetReturnValue().Set(obj);
605611
}
606612

@@ -1320,4 +1326,200 @@ NATIVE_FUNCTION(AllocatorObject, AllocDMA) {
13201326
args.GetReturnValue().Set(ret);
13211327
}
13221328

1329+
NATIVE_FUNCTION(LibsodiumObject, BlakeHash) {
1330+
PROLOGUE;
1331+
USEARG(0);
1332+
VALIDATEARG(0, STRING, "blake_hash: argument 0 is not a string");
1333+
1334+
v8::Local<v8::String> hashData = arg0->ToString(context).ToLocalChecked();
1335+
v8::String::Utf8Value hashData_utf8_val(hashData);
1336+
const char* hashData_str = *hashData_utf8_val;
1337+
1338+
unsigned char hash[crypto_generichash_BYTES];
1339+
1340+
crypto_generichash(hash, sizeof hash, (const unsigned char*)hashData_str, strlen(hashData_str), nullptr, 0);
1341+
1342+
char returnString[(sizeof(hash)/sizeof(unsigned char))*2 + 1];
1343+
1344+
for (int i = 0; i < (sizeof(hash)/sizeof(unsigned char)); i++) {
1345+
sprintf(&returnString[i*2], "%02X", hash[i]);
1346+
}
1347+
1348+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1349+
1350+
v8::Local<v8::String> ret;
1351+
if (!maybe_ret.ToLocal(&ret)) {
1352+
args.GetReturnValue().SetUndefined();
1353+
return;
1354+
}
1355+
1356+
args.GetReturnValue().Set(ret);
1357+
}
1358+
1359+
NATIVE_FUNCTION(LibsodiumObject, Sha256Hash) {
1360+
PROLOGUE;
1361+
USEARG(0);
1362+
VALIDATEARG(0, STRING, "sha256_hash: argument 0 is not a string");
1363+
1364+
v8::Local<v8::String> hashData = arg0->ToString(context).ToLocalChecked();
1365+
v8::String::Utf8Value hashData_utf8_val(hashData);
1366+
const char* hashData_str = *hashData_utf8_val;
1367+
1368+
unsigned char hash[crypto_hash_sha256_BYTES];
1369+
1370+
crypto_hash_sha256(hash, (const unsigned char*)hashData_str, strlen(hashData_str));
1371+
1372+
char returnString[(sizeof(hash)/sizeof(unsigned char))*2 + 1];
1373+
1374+
for (int i = 0; i < (sizeof(hash)/sizeof(unsigned char)); i++) {
1375+
sprintf(&returnString[i*2], "%02X", hash[i]);
1376+
}
1377+
1378+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1379+
1380+
v8::Local<v8::String> ret;
1381+
if (!maybe_ret.ToLocal(&ret)) {
1382+
args.GetReturnValue().SetUndefined();
1383+
return;
1384+
}
1385+
1386+
args.GetReturnValue().Set(ret);
1387+
}
1388+
1389+
NATIVE_FUNCTION(LibsodiumObject, Sha512Hash) {
1390+
PROLOGUE;
1391+
USEARG(0);
1392+
VALIDATEARG(0, STRING, "crypto_hash_sha512: argument 0 is not a string.");
1393+
1394+
v8::Local<v8::String> hashData = arg0->ToString(context).ToLocalChecked();
1395+
v8::String::Utf8Value hashData_utf8_val(hashData);
1396+
const char* hashData_str = *hashData_utf8_val;
1397+
1398+
unsigned char hash[crypto_hash_sha512_BYTES];
1399+
1400+
crypto_hash_sha512(hash, (const unsigned char*)hashData_str, strlen(hashData_str));
1401+
1402+
char returnString[(sizeof(hash)/sizeof(unsigned char))*2 + 1];
1403+
1404+
for (int i = 0; i < (sizeof(hash)/sizeof(unsigned char)); i++) {
1405+
sprintf(&returnString[i*2], "%02X", hash[i]);
1406+
}
1407+
1408+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1409+
1410+
v8::Local<v8::String> ret;
1411+
if (!maybe_ret.ToLocal(&ret)) {
1412+
args.GetReturnValue().SetUndefined();
1413+
return;
1414+
}
1415+
1416+
args.GetReturnValue().Set(ret);
1417+
}
1418+
1419+
NATIVE_FUNCTION(LibsodiumObject, Constants) {
1420+
PROLOGUE;
1421+
1422+
v8::Local<v8::Object> ret = v8::Object::New(iv8);
1423+
LOCAL_V8STRING(s_crypto_secretbox_NONCEBYTES, "crypto_secretbox_NONCEBYTES");
1424+
ret->Set(context, s_crypto_secretbox_NONCEBYTES, v8::Number::New(iv8, crypto_secretbox_NONCEBYTES));
1425+
1426+
args.GetReturnValue().Set(ret);
1427+
}
1428+
1429+
NATIVE_FUNCTION(LibsodiumObject, SecretboxEasy) {
1430+
PROLOGUE;
1431+
USEARG(0);
1432+
USEARG(1);
1433+
USEARG(2);
1434+
VALIDATEARG(0, STRING, "crypto_secretbox_easy: argument 0 is not a string.");
1435+
VALIDATEARG(1, STRING, "crypto_secretbox_easy: argument 1 is not a string.");
1436+
VALIDATEARG(2, OBJECT, "crypto_secretbox_easy: argument 2 is not a array/object.");
1437+
1438+
v8::Local<v8::String> encData = arg0->ToString(context).ToLocalChecked();
1439+
v8::String::Utf8Value encData_utf8_val(encData);
1440+
const char* encData_str = *encData_utf8_val;
1441+
1442+
v8::Local<v8::String> keyData = arg1->ToString(context).ToLocalChecked();
1443+
v8::String::Utf8Value keyData_utf8_val(keyData);
1444+
const char* keyData_str = *keyData_utf8_val;
1445+
1446+
v8::Local<v8::Object> nonceArray = arg2->ToObject(context).ToLocalChecked();
1447+
unsigned char nonceBytes[crypto_secretbox_NONCEBYTES];
1448+
1449+
for (int i = 0; i < (int)nonceArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value(); i++) {
1450+
nonceBytes[i] = (unsigned char)nonceArray->Get(i)->ToNumber()->Value();
1451+
}
1452+
1453+
unsigned char ciphertext[crypto_secretbox_MACBYTES + strlen(encData_str)];
1454+
1455+
crypto_secretbox_easy(ciphertext, (const unsigned char*)encData_str, strlen(encData_str), nonceBytes, (const unsigned char*)keyData_str);
1456+
1457+
char returnString[(sizeof(ciphertext)/sizeof(unsigned char))*2 + 1];
1458+
1459+
for (int i = 0; i < (sizeof(ciphertext)/sizeof(unsigned char)); i++) {
1460+
sprintf(&returnString[i*2], "%02X", ciphertext[i]);
1461+
}
1462+
1463+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1464+
1465+
v8::Local<v8::String> ret;
1466+
if (!maybe_ret.ToLocal(&ret)) {
1467+
args.GetReturnValue().SetUndefined();
1468+
return;
1469+
}
1470+
1471+
args.GetReturnValue().Set(ret);
1472+
}
1473+
1474+
NATIVE_FUNCTION(LibsodiumObject, SecretboxEasyOpen) {
1475+
PROLOGUE;
1476+
USEARG(0);
1477+
USEARG(1);
1478+
USEARG(2);
1479+
VALIDATEARG(0, OBJECT, "crypto_secretbox_easy_open: argument 0 is not a array/object.");
1480+
VALIDATEARG(1, STRING, "crypto_secretbox_easy_open: argument 1 is not a string.");
1481+
VALIDATEARG(2, OBJECT, "crypto_secretbox_easy_open: argument 2 is not a array/object.");
1482+
1483+
v8::Local<v8::Object> cipherArray = arg0->ToObject(context).ToLocalChecked();
1484+
unsigned char cipherBytes[(int)cipherArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value()];
1485+
1486+
for (int i = 0; i < (int)cipherArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value(); i++) {
1487+
cipherBytes[i] = (unsigned char)cipherArray->Get(i)->ToNumber()->Value();
1488+
}
1489+
1490+
v8::Local<v8::String> keyData = arg1->ToString(context).ToLocalChecked();
1491+
v8::String::Utf8Value keyData_utf8_val(keyData);
1492+
const char* keyData_str = *keyData_utf8_val;
1493+
1494+
v8::Local<v8::Object> nonceArray = arg2->ToObject(context).ToLocalChecked();
1495+
unsigned char nonceBytes[crypto_secretbox_NONCEBYTES];
1496+
1497+
for (int i = 0; i < (int)nonceArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value(); i++) {
1498+
nonceBytes[i] = (unsigned char)nonceArray->Get(i)->ToNumber()->Value();
1499+
}
1500+
1501+
unsigned char deciphertext[(int)cipherArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value() - crypto_secretbox_MACBYTES];
1502+
1503+
if (crypto_secretbox_open_easy(deciphertext, cipherBytes, (int)cipherArray->Get(v8::String::NewFromUtf8(iv8, "length", v8::NewStringType::kNormal).ToLocalChecked())->ToNumber()->Value(), nonceBytes, (const unsigned char*)keyData_str) != 0) {
1504+
args.GetReturnValue().SetUndefined();
1505+
return;
1506+
}
1507+
1508+
char returnString[(sizeof(deciphertext)/sizeof(unsigned char))*2 + 1];
1509+
1510+
for (int i = 0; i < (sizeof(deciphertext)/sizeof(unsigned char)); i++) {
1511+
sprintf(&returnString[i*2], "%02X", deciphertext[i]);
1512+
}
1513+
1514+
v8::MaybeLocal<v8::String> maybe_ret = v8::String::NewFromUtf8(iv8, returnString, v8::NewStringType::kNormal);
1515+
1516+
v8::Local<v8::String> ret;
1517+
if (!maybe_ret.ToLocal(&ret)) {
1518+
args.GetReturnValue().SetUndefined();
1519+
return;
1520+
}
1521+
1522+
args.GetReturnValue().Set(ret);
1523+
}
1524+
13231525
} // namespace rt

src/kernel/native-object.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,29 @@ class AllocatorObject : public JsObjectWrapper<AllocatorObject,
375375
private:
376376
};
377377

378+
class LibsodiumObject : public JsObjectWrapper<LibsodiumObject, NativeTypeId::TYPEID_LIBSODIUM> {
379+
public:
380+
LibsodiumObject() : JsObjectWrapper() {}
381+
382+
DECLARE_NATIVE(BlakeHash);
383+
DECLARE_NATIVE(Sha256Hash);
384+
DECLARE_NATIVE(Sha512Hash);
385+
DECLARE_NATIVE(Constants);
386+
DECLARE_NATIVE(SecretboxEasy);
387+
DECLARE_NATIVE(SecretboxEasyOpen);
388+
389+
void ObjectInit(ExportBuilder obj) {
390+
obj.SetCallback("crypto_generichash", BlakeHash);
391+
obj.SetCallback("crypto_hash_sha256", Sha256Hash);
392+
obj.SetCallback("crypto_hash_sha512", Sha512Hash);
393+
obj.SetCallback("crypto_constants", Constants);
394+
obj.SetCallback("crypto_secretbox_easy", SecretboxEasy);
395+
obj.SetCallback("crypto_secretbox_open_easy", SecretboxEasyOpen);
396+
}
397+
398+
JsObjectWrapperBase* Clone() const {
399+
return nullptr;
400+
}
401+
};
402+
378403
} // namespace rt

src/kernel/template-cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ enum class NativeTypeId : uint32_t {
4141
TYPEID_RESOURCE_IO_RANGE,
4242
TYPEID_ISOLATES_MANAGER,
4343
TYPEID_ALLOCATOR,
44+
TYPEID_LIBSODIUM,
4445
TYPEID_FUNCTION,
4546

4647
LAST // Keep it as the last element

0 commit comments

Comments
 (0)