diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 869c4396..6066b890 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -1,6 +1,12 @@ lib_LTLIBRARIES = \ libsodium.la +if !EMSCRIPTEN +libsodium_la_SOURCES += \ + randombytes/salsa20/randombytes_salsa20_random.c \ + randombytes/sysrandom/randombytes_sysrandom.c +endif + libsodium_la_SOURCES = \ crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c \ crypto_auth/crypto_auth.c \ @@ -149,8 +155,6 @@ 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 \ 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..8ab4b39e 100644 --- a/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c +++ b/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c @@ -241,10 +241,8 @@ randombytes_sysrandom_uniform(const uint32_t upper_bound) min = (uint32_t) (-upper_bound % upper_bound); for (;;) { 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;