Do not require /dev/urandom emulation in Javascript any more.

This commit is contained in:
Frank Denis 2015-01-17 21:42:50 +01:00
parent 201821065d
commit 9c0613525c
6 changed files with 92 additions and 40 deletions

View File

@ -1,6 +1,12 @@
lib_LTLIBRARIES = \ lib_LTLIBRARIES = \
libsodium.la libsodium.la
if !EMSCRIPTEN
libsodium_la_SOURCES += \
randombytes/salsa20/randombytes_salsa20_random.c \
randombytes/sysrandom/randombytes_sysrandom.c
endif
libsodium_la_SOURCES = \ libsodium_la_SOURCES = \
crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c \ crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c \
crypto_auth/crypto_auth.c \ crypto_auth/crypto_auth.c \
@ -149,8 +155,6 @@ libsodium_la_SOURCES = \
crypto_verify/64/ref/api.h \ crypto_verify/64/ref/api.h \
crypto_verify/64/ref/verify_64.c \ crypto_verify/64/ref/verify_64.c \
randombytes/randombytes.c \ randombytes/randombytes.c \
randombytes/salsa20/randombytes_salsa20_random.c \
randombytes/sysrandom/randombytes_sysrandom.c \
sodium/core.c \ sodium/core.c \
sodium/runtime.c \ sodium/runtime.c \
sodium/utils.c \ sodium/utils.c \

View File

@ -1,4 +1,8 @@
#ifdef __EMSCRIPTEN__
# include <emscripten.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <assert.h> #include <assert.h>
@ -8,8 +12,12 @@
#include "randombytes.h" #include "randombytes.h"
#include "randombytes_sysrandom.h" #include "randombytes_sysrandom.h"
#ifdef __EMSCRIPTEN__
static const randombytes_implementation *implementation = NULL;
#else
static const randombytes_implementation *implementation = static const randombytes_implementation *implementation =
&randombytes_sysrandom_implementation; &randombytes_sysrandom_implementation;
#endif
int int
randombytes_set_implementation(randombytes_implementation *impl) randombytes_set_implementation(randombytes_implementation *impl)
@ -22,39 +30,105 @@ randombytes_set_implementation(randombytes_implementation *impl)
const char * const char *
randombytes_implementation_name(void) randombytes_implementation_name(void)
{ {
#ifdef __EMSCRIPTEN__
return "js";
#else
return implementation->implementation_name(); return implementation->implementation_name();
#endif
} }
uint32_t uint32_t
randombytes_random(void) randombytes_random(void)
{ {
#ifdef __EMSCRIPTEN__
return EM_ASM_INT_V({
return Module.getRandomValue();
});
#else
return implementation->random(); return implementation->random();
#endif
} }
void void
randombytes_stir(void) randombytes_stir(void)
{ {
#ifdef __EMSCRIPTEN__
EM_ASM({
if (Module.getRandomValue === undefined) {
try {
var randomValuesStandard = function() {
var buf = new Uint16Array(1);
window.crypto.getRandomValues(buf);
return buf[0] >>> 0;
};
randomValuesStandard();
Module.getRandomValue = randomValuesStandard;
} catch (e) {
try {
var crypto = require('crypto');
var randomValueIOJS = function() {
var buf = crypto.randomBytes(2);
return (buf[0] << 8 | buf[1]) >>> 0;
};
randomValueIOJS();
Module.getRandomValue = randomValueIOJS;
} catch (e) {
throw 'No secure random number generator found';
}
}
}
});
#else
implementation->stir(); implementation->stir();
#endif
} }
uint32_t uint32_t
randombytes_uniform(const uint32_t upper_bound) randombytes_uniform(const uint32_t upper_bound)
{ {
#ifdef __EMSCRIPTEN__
uint32_t min;
uint32_t r;
if (upper_bound < 2) {
return 0;
}
min = (uint32_t) (-upper_bound % upper_bound);
do {
r = randombytes_random();
} while (r < min);
return r % upper_bound;
#else
return implementation->uniform(upper_bound); return implementation->uniform(upper_bound);
#endif
} }
void void
randombytes_buf(void * const buf, const size_t size) randombytes_buf(void * const buf, const size_t size)
{ {
#ifdef __EMSCRIPTEN__
unsigned char *p = buf;
size_t i;
for (i = (size_t) 0U; i < size; i++) {
p[i] = (unsigned char) randombytes_random();
}
#else
if (size > (size_t) 0U) { if (size > (size_t) 0U) {
implementation->buf(buf, size); implementation->buf(buf, size);
} }
#endif
} }
int int
randombytes_close(void) randombytes_close(void)
{ {
#ifdef __EMSCRIPTEN__
return 0;
#else
return implementation->close(); return implementation->close();
#endif
} }
void void

View File

@ -326,12 +326,10 @@ randombytes_salsa20_random_uniform(const uint32_t upper_bound)
return 0; return 0;
} }
min = (uint32_t) (-upper_bound % upper_bound); min = (uint32_t) (-upper_bound % upper_bound);
for (;;) { do {
r = randombytes_salsa20_random(); r = randombytes_salsa20_random();
if (r >= min) { } while (r < min); /* LCOV_EXCL_LINE */
break;
}
} /* LCOV_EXCL_LINE */
return r % upper_bound; return r % upper_bound;
} }

View File

@ -241,10 +241,8 @@ randombytes_sysrandom_uniform(const uint32_t upper_bound)
min = (uint32_t) (-upper_bound % upper_bound); min = (uint32_t) (-upper_bound % upper_bound);
for (;;) { for (;;) {
r = randombytes_sysrandom(); r = randombytes_sysrandom();
if (r >= min) { } while (r < min); /* LCOV_EXCL_LINE */
break;
}
} /* LCOV_EXCL_LINE */
return r % upper_bound; return r % upper_bound;
} }

View File

@ -6,34 +6,7 @@ try {
} }
Module['preRun'] = Module['preRun'] || []; Module['preRun'] = Module['preRun'] || [];
Module['preRun'].push(function(){ Module['preRun'].push(function(){
var randombyte = null;
try {
function randombyte_standard() {
var buf = new Int8Array(1);
window.crypto.getRandomValues(buf);
return buf[0];
}
randombyte_standard();
randombyte = randombyte_standard;
} catch (e) {
try {
var crypto = require('crypto');
function randombyte_node() {
return crypto.randomBytes(1)[0];
}
randombyte_node();
randombyte = randombyte_node;
} catch(e) {
throw 'No secure random number generator found';
}
}
FS.init(); FS.init();
FS.mkdir('/test-data'); FS.mkdir('/test-data');
FS.mount(NODEFS, { root: '.' }, '/test-data'); FS.mount(NODEFS, { root: '.' }, '/test-data');
FS.analyzePath('/dev/random').exists && FS.unlink('/dev/random');
FS.analyzePath('/dev/urandom') && FS.unlink('/dev/urandom');
var devFolder = FS.findObject('/dev') ||
Module['FS_createFolder']('/', 'dev', true, true);
Module['FS_createDevice'](devFolder, 'random', randombyte);
Module['FS_createDevice'](devFolder, 'urandom', randombyte);
}); });

View File

@ -29,8 +29,11 @@ static int randombytes_tests(void)
{ {
unsigned int i; unsigned int i;
assert(strcmp(randombytes_implementation_name(), "sysrandom") == 0); #ifdef __EMSCRIPTEN__
assert(strcmp(randombytes_implementation_name(), "sysrandom"));
#else
assert(strcmp(randombytes_implementation_name(), "js"));
#endif
randombytes(x, 1U); randombytes(x, 1U);
randombytes_close(); randombytes_close();
@ -47,8 +50,10 @@ static int randombytes_tests(void)
} }
assert(randombytes_uniform(1U) == 0U); assert(randombytes_uniform(1U) == 0U);
randombytes_close(); randombytes_close();
#ifndef __EMSCRIPTEN__
randombytes_set_implementation(&randombytes_salsa20_implementation); randombytes_set_implementation(&randombytes_salsa20_implementation);
assert(strcmp(randombytes_implementation_name(), "salsa20") == 0); assert(strcmp(randombytes_implementation_name(), "salsa20") == 0);
#endif
randombytes_stir(); randombytes_stir();
for (i = 0; i < 256; ++i) { for (i = 0; i < 256; ++i) {
freq[i] = 0; freq[i] = 0;