xref: /freebsd/sys/contrib/openzfs/lib/libspl/random.c (revision 8ac904ce090b1c2e355da8aa122ca2252183f4e1)
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