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