1/* Copyright libuv contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22#include "uv.h" 23#include "uv-common.h" 24 25#ifdef _WIN32 26# include "win/internal.h" 27#else 28# include "unix/internal.h" 29#endif 30 31static int uv__random(void* buf, size_t buflen) { 32 int rc; 33 34#if defined(__PASE__) 35 rc = uv__random_readpath("/dev/urandom", buf, buflen); 36#elif defined(_AIX) || defined(__QNX__) 37 rc = uv__random_readpath("/dev/random", buf, buflen); 38#elif defined(__APPLE__) || defined(__OpenBSD__) || \ 39 (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) 40 rc = uv__random_getentropy(buf, buflen); 41 if (rc == UV_ENOSYS) 42 rc = uv__random_devurandom(buf, buflen); 43#elif defined(__NetBSD__) 44 rc = uv__random_sysctl(buf, buflen); 45#elif defined(__FreeBSD__) || defined(__linux__) 46 rc = uv__random_getrandom(buf, buflen); 47 if (rc == UV_ENOSYS) 48 rc = uv__random_devurandom(buf, buflen); 49# if defined(__linux__) 50 switch (rc) { 51 case UV_EACCES: 52 case UV_EIO: 53 case UV_ELOOP: 54 case UV_EMFILE: 55 case UV_ENFILE: 56 case UV_ENOENT: 57 case UV_EPERM: 58 rc = uv__random_sysctl(buf, buflen); 59 break; 60 } 61# endif 62#elif defined(_WIN32) 63 uv__once_init(); 64 rc = uv__random_rtlgenrandom(buf, buflen); 65#else 66 rc = uv__random_devurandom(buf, buflen); 67#endif 68 69 return rc; 70} 71 72 73static void uv__random_work(struct uv__work* w) { 74 uv_random_t* req; 75 76 req = container_of(w, uv_random_t, work_req); 77 req->status = uv__random(req->buf, req->buflen); 78} 79 80 81static void uv__random_done(struct uv__work* w, int status) { 82 uv_random_t* req; 83 84 req = container_of(w, uv_random_t, work_req); 85 uv__req_unregister(req->loop, req); 86 87 if (status == 0) 88 status = req->status; 89 90 req->cb(req, status, req->buf, req->buflen); 91} 92 93 94int uv_random(uv_loop_t* loop, 95 uv_random_t* req, 96 void *buf, 97 size_t buflen, 98 unsigned flags, 99 uv_random_cb cb) { 100 if (buflen > 0x7FFFFFFFu) 101 return UV_E2BIG; 102 103 if (flags != 0) 104 return UV_EINVAL; 105 106 if (cb == NULL) 107 return uv__random(buf, buflen); 108 109 uv__req_init(loop, req, UV_RANDOM); 110 req->loop = loop; 111 req->status = 0; 112 req->cb = cb; 113 req->buf = buf; 114 req->buflen = buflen; 115 116 uv__work_submit(loop, 117 &req->work_req, 118 UV__WORK_CPU, 119 uv__random_work, 120 uv__random_done); 121 122 return 0; 123} 124