diff --git a/jpm b/jpm index 104922e5..c3433334 100755 --- a/jpm +++ b/jpm @@ -535,6 +535,16 @@ ``` int main(int argc, const char **argv) { + +#if defined(JANET_PRF) + uint8_t hash_key[JANET_HASH_KEY_SIZE]; + if (janet_cryptorand(hash_key, JANET_HASH_KEY_SIZE) != 0) { + fputs("unable to initialize janet PRF hash function.\n", stderr); + return 1; + } + janet_init_hash_key(hash_key); +#endif + janet_init(); /* Get core env */ diff --git a/src/core/os.c b/src/core/os.c index 1b794890..fc90ba7b 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -37,8 +37,6 @@ #include #include -#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR) - #ifdef JANET_APPLE #include #endif @@ -68,12 +66,6 @@ extern char **environ; #include #endif -/* Setting C99 standard makes this not available, but it should - * work/link properly if we detect a BSD */ -#if defined(JANET_BSD) || defined(MAC_OS_X_VERSION_10_7) -void arc4random_buf(void *buf, size_t nbytes); -#endif - /* Not POSIX, but all Unixes but Solaris have this function. */ #if defined(JANET_POSIX) && !defined(__sun) time_t timegm(struct tm *tm); @@ -557,7 +549,6 @@ static Janet os_cwd(int32_t argc, Janet *argv) { static Janet os_cryptorand(int32_t argc, Janet *argv) { JanetBuffer *buffer; - const char *genericerr = "unable to get sufficient random data"; janet_arity(argc, 1, 2); int32_t offset; int32_t n = janet_getinteger(argv, 0); @@ -572,44 +563,9 @@ static Janet os_cryptorand(int32_t argc, Janet *argv) { /* We could optimize here by adding setcount_uninit */ janet_buffer_setcount(buffer, offset + n); -#ifdef JANET_WINDOWS - for (int32_t i = offset; i < buffer->count; i += sizeof(unsigned int)) { - unsigned int v; - if (rand_s(&v)) - janet_panic(genericerr); - for (int32_t j = 0; (j < sizeof(unsigned int)) && (i + j < buffer->count); j++) { - buffer->data[i + j] = v & 0xff; - v = v >> 8; - } - } -#elif defined(JANET_LINUX) || ( defined(JANET_APPLE) && !defined(MAC_OS_X_VERSION_10_7) ) - /* We should be able to call getrandom on linux, but it doesn't seem - to be uniformly supported on linux distros. - On Mac, arc4random_buf wasn't available on until 10.7. - In these cases, use this fallback path for now... */ - int rc; - int randfd; - RETRY_EINTR(randfd, open("/dev/urandom", O_RDONLY | O_CLOEXEC)); - if (randfd < 0) - janet_panic(genericerr); - while (n > 0) { - ssize_t nread; - RETRY_EINTR(nread, read(randfd, buffer->data + offset, n)); - if (nread <= 0) { - RETRY_EINTR(rc, close(randfd)); - janet_panic(genericerr); - } - offset += nread; - n -= nread; - } - RETRY_EINTR(rc, close(randfd)); -#elif defined(JANET_BSD) || defined(MAC_OS_X_VERSION_10_7) - (void) genericerr; - arc4random_buf(buffer->data + offset, n); -#else - (void) genericerr; - janet_panic("cryptorand currently unsupported on this platform"); -#endif + if (janet_cryptorand(buffer->data + offset, n) != 0) + janet_panic("unable to get sufficient random data"); + return janet_wrap_buffer(buffer); } diff --git a/src/core/util.c b/src/core/util.c index 31855c8f..d1e4f5b5 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -28,6 +28,11 @@ #include "gc.h" #ifdef JANET_WINDOWS #include +#else +#include +#include +#include +#include #endif #endif @@ -630,3 +635,51 @@ int janet_gettime(struct timespec *spec) { } #endif #endif + +/* Setting C99 standard makes this not available, but it should + * work/link properly if we detect a BSD */ +#if defined(JANET_BSD) || defined(MAC_OS_X_VERSION_10_7) +void arc4random_buf(void *buf, size_t nbytes); +#endif + +int janet_cryptorand(uint8_t *out, size_t n) { +#ifdef JANET_WINDOWS + for (size_t i = 0; i < n; i += sizeof(unsigned int)) { + unsigned int v; + if (rand_s(&v)) + return -1; + for (int32_t j = 0; (j < sizeof(unsigned int)) && (i + j < n); j++) { + out[i + j] = v & 0xff; + v = v >> 8; + } + } + return 0; +#elif defined(JANET_LINUX) || ( defined(JANET_APPLE) && !defined(MAC_OS_X_VERSION_10_7) ) + /* We should be able to call getrandom on linux, but it doesn't seem + to be uniformly supported on linux distros. + On Mac, arc4random_buf wasn't available on until 10.7. + In these cases, use this fallback path for now... */ + int rc; + int randfd; + RETRY_EINTR(randfd, open("/dev/urandom", O_RDONLY | O_CLOEXEC)); + if (randfd < 0) + return -1; + while (n > 0) { + ssize_t nread; + RETRY_EINTR(nread, read(randfd, out, n)); + if (nread <= 0) { + RETRY_EINTR(rc, close(randfd)); + return -1; + } + out += nread; + n -= nread; + } + RETRY_EINTR(rc, close(randfd)); + return 0; +#elif defined(JANET_BSD) || defined(MAC_OS_X_VERSION_10_7) + arc4random_buf(out, sz); + return 0; +#else + return -1; +#endif +} \ No newline at end of file diff --git a/src/core/util.h b/src/core/util.h index 70090a52..0679ffba 100644 --- a/src/core/util.h +++ b/src/core/util.h @@ -108,6 +108,8 @@ void janet_core_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cf int janet_gettime(struct timespec *spec); #endif +#define RETRY_EINTR(RC, CALL) do { (RC) = CALL; } while((RC) < 0 && errno == EINTR) + /* Initialize builtin libraries */ void janet_lib_io(JanetTable *env); void janet_lib_math(JanetTable *env); diff --git a/src/include/janet.h b/src/include/janet.h index 0046e730..b6de1287 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1545,6 +1545,8 @@ JANET_API FILE *janet_dynfile(const char *name, FILE *def); JANET_API JanetAbstract janet_checkfile(Janet j); JANET_API FILE *janet_unwrapfile(Janet j, int32_t *flags); +int janet_cryptorand(uint8_t *out, size_t n); + /* Marshal API */ JANET_API void janet_marshal_size(JanetMarshalContext *ctx, size_t value); JANET_API void janet_marshal_int(JanetMarshalContext *ctx, int32_t value); diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index e1628eac..99bb0a30 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -1017,6 +1017,15 @@ int main(int argc, char **argv) { atexit(norawmode); #endif +#if defined(JANET_PRF) + uint8_t hash_key[JANET_HASH_KEY_SIZE]; + if (janet_cryptorand(hash_key, JANET_HASH_KEY_SIZE) != 0) { + fputs("unable to initialize janet PRF hash function.\n", stderr); + return 1; + } + janet_init_hash_key(hash_key); +#endif + /* Set up VM */ janet_init();