From c64baf38c6b12dc781dfa6da35b0cea9a137235d Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 17 Jan 2015 21:42:50 +0100 Subject: [PATCH 1/2] Do not require /dev/urandom emulation in Javascript any more. --- src/libsodium/Makefile.am | 8 +- src/libsodium/randombytes/randombytes.c | 74 +++++++++++++++++++ .../salsa20/randombytes_salsa20_random.c | 8 +- .../sysrandom/randombytes_sysrandom.c | 8 +- test/default/pre.js.inc | 27 ------- test/default/randombytes.c | 9 ++- 6 files changed, 93 insertions(+), 41 deletions(-) diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 869c4396..c45119dc 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -149,13 +149,17 @@ libsodium_la_SOURCES = \ crypto_verify/64/ref/api.h \ crypto_verify/64/ref/verify_64.c \ randombytes/randombytes.c \ - randombytes/salsa20/randombytes_salsa20_random.c \ - randombytes/sysrandom/randombytes_sysrandom.c \ sodium/core.c \ sodium/runtime.c \ sodium/utils.c \ sodium/version.c +if !EMSCRIPTEN +libsodium_la_SOURCES += \ + randombytes/salsa20/randombytes_salsa20_random.c \ + randombytes/sysrandom/randombytes_sysrandom.c +endif + if HAVE_TI_MODE libsodium_la_SOURCES += \ crypto_scalarmult/curve25519/donna_c64/api.h \ diff --git a/src/libsodium/randombytes/randombytes.c b/src/libsodium/randombytes/randombytes.c index 07e23410..b92943bf 100644 --- a/src/libsodium/randombytes/randombytes.c +++ b/src/libsodium/randombytes/randombytes.c @@ -1,4 +1,8 @@ +#ifdef __EMSCRIPTEN__ +# include +#endif + #include #include @@ -8,8 +12,12 @@ #include "randombytes.h" #include "randombytes_sysrandom.h" +#ifdef __EMSCRIPTEN__ +static const randombytes_implementation *implementation = NULL; +#else static const randombytes_implementation *implementation = &randombytes_sysrandom_implementation; +#endif int randombytes_set_implementation(randombytes_implementation *impl) @@ -22,39 +30,105 @@ randombytes_set_implementation(randombytes_implementation *impl) const char * randombytes_implementation_name(void) { +#ifdef __EMSCRIPTEN__ + return "js"; +#else return implementation->implementation_name(); +#endif } uint32_t randombytes_random(void) { +#ifdef __EMSCRIPTEN__ + return EM_ASM_INT_V({ + return Module.getRandomValue(); + }); +#else return implementation->random(); +#endif } 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(); +#endif } uint32_t 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); +#endif } void 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) { implementation->buf(buf, size); } +#endif } int randombytes_close(void) { +#ifdef __EMSCRIPTEN__ + return 0; +#else return implementation->close(); +#endif } void diff --git a/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c b/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c index 3d7627d2..e81fa92d 100644 --- a/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c +++ b/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c @@ -326,12 +326,10 @@ randombytes_salsa20_random_uniform(const uint32_t upper_bound) return 0; } min = (uint32_t) (-upper_bound % upper_bound); - for (;;) { + do { r = randombytes_salsa20_random(); - if (r >= min) { - break; - } - } /* LCOV_EXCL_LINE */ + } while (r < min); /* LCOV_EXCL_LINE */ + return r % upper_bound; } diff --git a/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c b/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c index 15b223b4..539ebca6 100644 --- a/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c +++ b/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c @@ -239,12 +239,10 @@ randombytes_sysrandom_uniform(const uint32_t upper_bound) return 0; } min = (uint32_t) (-upper_bound % upper_bound); - for (;;) { + do { r = randombytes_sysrandom(); - if (r >= min) { - break; - } - } /* LCOV_EXCL_LINE */ + } while (r < min); /* LCOV_EXCL_LINE */ + return r % upper_bound; } diff --git a/test/default/pre.js.inc b/test/default/pre.js.inc index 27975c2e..428f475d 100755 --- a/test/default/pre.js.inc +++ b/test/default/pre.js.inc @@ -6,34 +6,7 @@ try { } Module['preRun'] = Module['preRun'] || []; 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.mkdir('/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); }); diff --git a/test/default/randombytes.c b/test/default/randombytes.c index f9f337f3..ece21d61 100644 --- a/test/default/randombytes.c +++ b/test/default/randombytes.c @@ -29,8 +29,11 @@ static int randombytes_tests(void) { 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_close(); @@ -47,8 +50,10 @@ static int randombytes_tests(void) } assert(randombytes_uniform(1U) == 0U); randombytes_close(); +#ifndef __EMSCRIPTEN__ randombytes_set_implementation(&randombytes_salsa20_implementation); assert(strcmp(randombytes_implementation_name(), "salsa20") == 0); +#endif randombytes_stir(); for (i = 0; i < 256; ++i) { freq[i] = 0; From 3d5c00a581aacc2ce84bfb998bab05415ab0071c Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Sat, 17 Jan 2015 22:11:10 +0100 Subject: [PATCH 2/2] Emscripten: don't use a memory init file any more. It doesn't take that long to load the module, and it's going to make users' life way easier. --- configure.ac | 2 +- dist-build/emscripten.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index edf9c519..69cae492 100644 --- a/configure.ac +++ b/configure.ac @@ -423,7 +423,7 @@ AC_SUBST([LIBTOOL_EXTRA_FLAGS]) TEST_LDFLAGS='' AS_IF([test "x$EMSCRIPTEN" != "x"],[ EXEEXT=.js - TEST_LDFLAGS='--pre-js pre.js.inc -s RESERVED_FUNCTION_POINTERS=8' + TEST_LDFLAGS='--memory-init-file 0 --pre-js pre.js.inc -s RESERVED_FUNCTION_POINTERS=8' ]) AC_SUBST(TEST_LDFLAGS) AM_CONDITIONAL([EMSCRIPTEN], [test "x$EMSCRIPTEN" != "x"]) diff --git a/dist-build/emscripten.sh b/dist-build/emscripten.sh index 0d4c9664..03d0818f 100755 --- a/dist-build/emscripten.sh +++ b/dist-build/emscripten.sh @@ -13,7 +13,7 @@ emconfigure ./configure --enable-minimal --disable-shared --prefix="$PREFIX" \ CFLAGS="-O3" && \ emmake make clean && \ emmake make $MAKE_FLAGS install V=1 && \ -emcc -O3 --closure 1 --llvm-lto 1 $LDFLAGS $JS_EXPORTS_FLAGS \ +emcc -O3 --closure 1 --llvm-lto 1 --memory-init-file 0 $LDFLAGS $JS_EXPORTS_FLAGS \ "${PREFIX}/lib/libsodium.a" -o "${PREFIX}/lib/libsodium.js" || exit 1 if test "x$NODE" = x; then