1*8ac904ceSMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2*8ac904ceSMartin Matuska /*
3*8ac904ceSMartin Matuska * CDDL HEADER START
4*8ac904ceSMartin Matuska *
5*8ac904ceSMartin Matuska * The contents of this file are subject to the terms of the
6*8ac904ceSMartin Matuska * Common Development and Distribution License (the "License").
7*8ac904ceSMartin Matuska * You may not use this file except in compliance with the License.
8*8ac904ceSMartin Matuska *
9*8ac904ceSMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*8ac904ceSMartin Matuska * or https://opensource.org/licenses/CDDL-1.0.
11*8ac904ceSMartin Matuska * See the License for the specific language governing permissions
12*8ac904ceSMartin Matuska * and limitations under the License.
13*8ac904ceSMartin Matuska *
14*8ac904ceSMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each
15*8ac904ceSMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*8ac904ceSMartin Matuska * If applicable, add the following below this CDDL HEADER, with the
17*8ac904ceSMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying
18*8ac904ceSMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner]
19*8ac904ceSMartin Matuska *
20*8ac904ceSMartin Matuska * CDDL HEADER END
21*8ac904ceSMartin Matuska */
22*8ac904ceSMartin Matuska /*
23*8ac904ceSMartin Matuska * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24*8ac904ceSMartin Matuska * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
25*8ac904ceSMartin Matuska * Copyright (c) 2016 Actifio, Inc. All rights reserved.
26*8ac904ceSMartin Matuska * Copyright (c) 2025, Klara, Inc.
27*8ac904ceSMartin Matuska */
28*8ac904ceSMartin Matuska
29*8ac904ceSMartin Matuska #include <stdint.h>
30*8ac904ceSMartin Matuska #include <fcntl.h>
31*8ac904ceSMartin Matuska #include <assert.h>
32*8ac904ceSMartin Matuska #include <sys/random.h>
33*8ac904ceSMartin Matuska #include "libspl_impl.h"
34*8ac904ceSMartin Matuska
35*8ac904ceSMartin Matuska #define RANDOM_PATH "/dev/random"
36*8ac904ceSMartin Matuska #define URANDOM_PATH "/dev/urandom"
37*8ac904ceSMartin Matuska
38*8ac904ceSMartin Matuska static int random_fd = -1, urandom_fd = -1;
39*8ac904ceSMartin Matuska
40*8ac904ceSMartin Matuska static boolean_t force_pseudo = B_FALSE;
41*8ac904ceSMartin Matuska
42*8ac904ceSMartin Matuska void
random_init(void)43*8ac904ceSMartin Matuska random_init(void)
44*8ac904ceSMartin Matuska {
45*8ac904ceSMartin Matuska /* Handle multiple calls. */
46*8ac904ceSMartin Matuska if (random_fd != -1) {
47*8ac904ceSMartin Matuska ASSERT3U(urandom_fd, !=, -1);
48*8ac904ceSMartin Matuska return;
49*8ac904ceSMartin Matuska }
50*8ac904ceSMartin Matuska
51*8ac904ceSMartin Matuska VERIFY((random_fd = open(RANDOM_PATH, O_RDONLY | O_CLOEXEC)) != -1);
52*8ac904ceSMartin Matuska VERIFY((urandom_fd = open(URANDOM_PATH, O_RDONLY | O_CLOEXEC)) != -1);
53*8ac904ceSMartin Matuska }
54*8ac904ceSMartin Matuska
55*8ac904ceSMartin Matuska void
random_fini(void)56*8ac904ceSMartin Matuska random_fini(void)
57*8ac904ceSMartin Matuska {
58*8ac904ceSMartin Matuska close(random_fd);
59*8ac904ceSMartin Matuska close(urandom_fd);
60*8ac904ceSMartin Matuska
61*8ac904ceSMartin Matuska random_fd = -1;
62*8ac904ceSMartin Matuska urandom_fd = -1;
63*8ac904ceSMartin Matuska }
64*8ac904ceSMartin Matuska
65*8ac904ceSMartin Matuska void
random_force_pseudo(boolean_t onoff)66*8ac904ceSMartin Matuska random_force_pseudo(boolean_t onoff)
67*8ac904ceSMartin Matuska {
68*8ac904ceSMartin Matuska force_pseudo = onoff;
69*8ac904ceSMartin Matuska }
70*8ac904ceSMartin Matuska
71*8ac904ceSMartin Matuska static int
random_get_bytes_common(uint8_t * ptr,size_t len,int fd)72*8ac904ceSMartin Matuska random_get_bytes_common(uint8_t *ptr, size_t len, int fd)
73*8ac904ceSMartin Matuska {
74*8ac904ceSMartin Matuska size_t resid = len;
75*8ac904ceSMartin Matuska ssize_t bytes;
76*8ac904ceSMartin Matuska
77*8ac904ceSMartin Matuska ASSERT(fd != -1);
78*8ac904ceSMartin Matuska
79*8ac904ceSMartin Matuska while (resid != 0) {
80*8ac904ceSMartin Matuska bytes = read(fd, ptr, resid);
81*8ac904ceSMartin Matuska ASSERT3S(bytes, >=, 0);
82*8ac904ceSMartin Matuska ptr += bytes;
83*8ac904ceSMartin Matuska resid -= bytes;
84*8ac904ceSMartin Matuska }
85*8ac904ceSMartin Matuska
86*8ac904ceSMartin Matuska return (0);
87*8ac904ceSMartin Matuska }
88*8ac904ceSMartin Matuska
89*8ac904ceSMartin Matuska int
random_get_bytes(uint8_t * ptr,size_t len)90*8ac904ceSMartin Matuska random_get_bytes(uint8_t *ptr, size_t len)
91*8ac904ceSMartin Matuska {
92*8ac904ceSMartin Matuska if (force_pseudo)
93*8ac904ceSMartin Matuska return (random_get_pseudo_bytes(ptr, len));
94*8ac904ceSMartin Matuska return (random_get_bytes_common(ptr, len, random_fd));
95*8ac904ceSMartin Matuska }
96*8ac904ceSMartin Matuska
97*8ac904ceSMartin Matuska int
random_get_pseudo_bytes(uint8_t * ptr,size_t len)98*8ac904ceSMartin Matuska random_get_pseudo_bytes(uint8_t *ptr, size_t len)
99*8ac904ceSMartin Matuska {
100*8ac904ceSMartin Matuska return (random_get_bytes_common(ptr, len, urandom_fd));
101*8ac904ceSMartin Matuska }
102