xref: /third_party/node/deps/uv/src/random.c (revision 1cb0ef41)
11cb0ef41Sopenharmony_ci/* Copyright libuv contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "uv.h"
231cb0ef41Sopenharmony_ci#include "uv-common.h"
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci#ifdef _WIN32
261cb0ef41Sopenharmony_ci#  include "win/internal.h"
271cb0ef41Sopenharmony_ci#else
281cb0ef41Sopenharmony_ci#  include "unix/internal.h"
291cb0ef41Sopenharmony_ci#endif
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cistatic int uv__random(void* buf, size_t buflen) {
321cb0ef41Sopenharmony_ci  int rc;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#if defined(__PASE__)
351cb0ef41Sopenharmony_ci  rc = uv__random_readpath("/dev/urandom", buf, buflen);
361cb0ef41Sopenharmony_ci#elif defined(_AIX) || defined(__QNX__)
371cb0ef41Sopenharmony_ci  rc = uv__random_readpath("/dev/random", buf, buflen);
381cb0ef41Sopenharmony_ci#elif defined(__APPLE__) || defined(__OpenBSD__) || \
391cb0ef41Sopenharmony_ci     (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
401cb0ef41Sopenharmony_ci  rc = uv__random_getentropy(buf, buflen);
411cb0ef41Sopenharmony_ci  if (rc == UV_ENOSYS)
421cb0ef41Sopenharmony_ci    rc = uv__random_devurandom(buf, buflen);
431cb0ef41Sopenharmony_ci#elif defined(__NetBSD__)
441cb0ef41Sopenharmony_ci  rc = uv__random_sysctl(buf, buflen);
451cb0ef41Sopenharmony_ci#elif defined(__FreeBSD__) || defined(__linux__)
461cb0ef41Sopenharmony_ci  rc = uv__random_getrandom(buf, buflen);
471cb0ef41Sopenharmony_ci  if (rc == UV_ENOSYS)
481cb0ef41Sopenharmony_ci    rc = uv__random_devurandom(buf, buflen);
491cb0ef41Sopenharmony_ci# if defined(__linux__)
501cb0ef41Sopenharmony_ci  switch (rc) {
511cb0ef41Sopenharmony_ci    case UV_EACCES:
521cb0ef41Sopenharmony_ci    case UV_EIO:
531cb0ef41Sopenharmony_ci    case UV_ELOOP:
541cb0ef41Sopenharmony_ci    case UV_EMFILE:
551cb0ef41Sopenharmony_ci    case UV_ENFILE:
561cb0ef41Sopenharmony_ci    case UV_ENOENT:
571cb0ef41Sopenharmony_ci    case UV_EPERM:
581cb0ef41Sopenharmony_ci      rc = uv__random_sysctl(buf, buflen);
591cb0ef41Sopenharmony_ci      break;
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci# endif
621cb0ef41Sopenharmony_ci#elif defined(_WIN32)
631cb0ef41Sopenharmony_ci  uv__once_init();
641cb0ef41Sopenharmony_ci  rc = uv__random_rtlgenrandom(buf, buflen);
651cb0ef41Sopenharmony_ci#else
661cb0ef41Sopenharmony_ci  rc = uv__random_devurandom(buf, buflen);
671cb0ef41Sopenharmony_ci#endif
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci  return rc;
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_cistatic void uv__random_work(struct uv__work* w) {
741cb0ef41Sopenharmony_ci  uv_random_t* req;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  req = container_of(w, uv_random_t, work_req);
771cb0ef41Sopenharmony_ci  req->status = uv__random(req->buf, req->buflen);
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_cistatic void uv__random_done(struct uv__work* w, int status) {
821cb0ef41Sopenharmony_ci  uv_random_t* req;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  req = container_of(w, uv_random_t, work_req);
851cb0ef41Sopenharmony_ci  uv__req_unregister(req->loop, req);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  if (status == 0)
881cb0ef41Sopenharmony_ci    status = req->status;
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  req->cb(req, status, req->buf, req->buflen);
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ciint uv_random(uv_loop_t* loop,
951cb0ef41Sopenharmony_ci              uv_random_t* req,
961cb0ef41Sopenharmony_ci              void *buf,
971cb0ef41Sopenharmony_ci              size_t buflen,
981cb0ef41Sopenharmony_ci              unsigned flags,
991cb0ef41Sopenharmony_ci              uv_random_cb cb) {
1001cb0ef41Sopenharmony_ci  if (buflen > 0x7FFFFFFFu)
1011cb0ef41Sopenharmony_ci    return UV_E2BIG;
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  if (flags != 0)
1041cb0ef41Sopenharmony_ci    return UV_EINVAL;
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  if (cb == NULL)
1071cb0ef41Sopenharmony_ci    return uv__random(buf, buflen);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  uv__req_init(loop, req, UV_RANDOM);
1101cb0ef41Sopenharmony_ci  req->loop = loop;
1111cb0ef41Sopenharmony_ci  req->status = 0;
1121cb0ef41Sopenharmony_ci  req->cb = cb;
1131cb0ef41Sopenharmony_ci  req->buf = buf;
1141cb0ef41Sopenharmony_ci  req->buflen = buflen;
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  uv__work_submit(loop,
1171cb0ef41Sopenharmony_ci                  &req->work_req,
1181cb0ef41Sopenharmony_ci                  UV__WORK_CPU,
1191cb0ef41Sopenharmony_ci                  uv__random_work,
1201cb0ef41Sopenharmony_ci                  uv__random_done);
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  return 0;
1231cb0ef41Sopenharmony_ci}
124