diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2019-06-22 15:18:17 +0200 |
---|---|---|
committer | Saúl Ibarra Corretgé <s@saghul.net> | 2019-09-18 08:09:14 +0200 |
commit | 4ed2a78f0eb1c9d2a0c98ea4a88c6824e5958dc6 (patch) | |
tree | ce6b8b3282f3ac65d6bbeba5cec36463b68f06e5 /src/unix/random-getrandom.c | |
parent | fd1502f5630591bf8ce79502df9b5d76868dfd3b (diff) | |
download | libuv-4ed2a78f0eb1c9d2a0c98ea4a88c6824e5958dc6.tar.gz libuv-4ed2a78f0eb1c9d2a0c98ea4a88c6824e5958dc6.zip |
unix,win: add uv_random()
Add an API for obtaining cryptographically strong random data from the
system PRNG.
Co-authored-by: Saúl Ibarra Corretgé <s@saghul.net>
Refs: https://github.com/libuv/libuv/pull/1055
PR-URL: https://github.com/libuv/libuv/pull/2347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Diffstat (limited to 'src/unix/random-getrandom.c')
-rw-r--r-- | src/unix/random-getrandom.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/unix/random-getrandom.c b/src/unix/random-getrandom.c new file mode 100644 index 00000000..bcc94089 --- /dev/null +++ b/src/unix/random-getrandom.c @@ -0,0 +1,88 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#ifdef __linux__ + +#include "linux-syscalls.h" + +#define uv__random_getrandom_init() 0 + +#else /* !__linux__ */ + +#include <stddef.h> +#include <dlfcn.h> + +typedef ssize_t (*uv__getrandom_cb)(void *, size_t, unsigned); + +static uv__getrandom_cb uv__getrandom; +static uv_once_t once = UV_ONCE_INIT; + +static void uv__random_getrandom_init_once(void) { + uv__getrandom = (uv__getrandom_cb) dlsym(RTLD_DEFAULT, "getrandom"); +} + +static int uv__random_getrandom_init(void) { + uv_once(&once, uv__random_getrandom_init_once); + + if (uv__getrandom == NULL) + return UV_ENOSYS; + + return 0; +} + +#endif /* !__linux__ */ + +int uv__random_getrandom(void* buf, size_t buflen) { + ssize_t n; + size_t pos; + int rc; + + rc = uv__random_getrandom_init(); + if (rc != 0) + return rc; + + for (pos = 0; pos != buflen; pos += n) { + do { + n = buflen - pos; + + /* Most getrandom() implementations promise that reads <= 256 bytes + * will always succeed and won't be interrupted by signals. + * It's therefore useful to split it up in smaller reads because + * one big read may, in theory, continuously fail with EINTR. + */ + if (n > 256) + n = 256; + + n = uv__getrandom((char *) buf + pos, n, 0); + } while (n == -1 && errno == EINTR); + + if (n == -1) + return UV__ERR(errno); + + if (n == 0) + return UV_EIO; + } + + return 0; +} |