xref: /illumos-gate/usr/src/uts/common/syscall/getrandom.c (revision 9d12795f87b63c2e39e87bff369182edd34677d3)
1*9d12795fSRobert Mustacchi /*
2*9d12795fSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*9d12795fSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*9d12795fSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*9d12795fSRobert Mustacchi  * 1.0 of the CDDL.
6*9d12795fSRobert Mustacchi  *
7*9d12795fSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*9d12795fSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*9d12795fSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*9d12795fSRobert Mustacchi  */
11*9d12795fSRobert Mustacchi 
12*9d12795fSRobert Mustacchi /*
13*9d12795fSRobert Mustacchi  * Copyright (c) 2015, Joyent, Inc.
14*9d12795fSRobert Mustacchi  */
15*9d12795fSRobert Mustacchi 
16*9d12795fSRobert Mustacchi /*
17*9d12795fSRobert Mustacchi  * getrandom system call implementation
18*9d12795fSRobert Mustacchi  */
19*9d12795fSRobert Mustacchi 
20*9d12795fSRobert Mustacchi #include <sys/types.h>
21*9d12795fSRobert Mustacchi #include <sys/errno.h>
22*9d12795fSRobert Mustacchi #include <sys/systm.h>
23*9d12795fSRobert Mustacchi #include <sys/random.h>
24*9d12795fSRobert Mustacchi #include <sys/ddi.h>
25*9d12795fSRobert Mustacchi #include <sys/sunddi.h>
26*9d12795fSRobert Mustacchi #include <sys/sysmacros.h>
27*9d12795fSRobert Mustacchi 
28*9d12795fSRobert Mustacchi #include <sys/random.h>
29*9d12795fSRobert Mustacchi 
30*9d12795fSRobert Mustacchi /*
31*9d12795fSRobert Mustacchi  * Impose a maximum upper bound on the number of bytes that we'll read in one
32*9d12795fSRobert Mustacchi  * go, ala a read of /dev/random. For /dev/urandom, we clamp it based on our
33*9d12795fSRobert Mustacchi  * return value, because the system call returns an int, we can't handle more
34*9d12795fSRobert Mustacchi  * than INT_MAX.
35*9d12795fSRobert Mustacchi  */
36*9d12795fSRobert Mustacchi #define	MAXRANDBYTES	1024
37*9d12795fSRobert Mustacchi #define	MAXURANDBYTES	INT_MAX
38*9d12795fSRobert Mustacchi 
39*9d12795fSRobert Mustacchi int
40*9d12795fSRobert Mustacchi getrandom(void *bufp, size_t buflen, int flags)
41*9d12795fSRobert Mustacchi {
42*9d12795fSRobert Mustacchi 	int out = 0;
43*9d12795fSRobert Mustacchi 	uint8_t rbytes[128];
44*9d12795fSRobert Mustacchi 	uint8_t *buf = bufp;
45*9d12795fSRobert Mustacchi 
46*9d12795fSRobert Mustacchi 	if (flags & ~(GRND_NONBLOCK | GRND_RANDOM))
47*9d12795fSRobert Mustacchi 		return (set_errno(EINVAL));
48*9d12795fSRobert Mustacchi 
49*9d12795fSRobert Mustacchi 	if ((flags & GRND_RANDOM) && buflen > MAXRANDBYTES) {
50*9d12795fSRobert Mustacchi 		buflen = MAXRANDBYTES;
51*9d12795fSRobert Mustacchi 	} else if (buflen > MAXURANDBYTES) {
52*9d12795fSRobert Mustacchi 		buflen = MAXURANDBYTES;
53*9d12795fSRobert Mustacchi 	}
54*9d12795fSRobert Mustacchi 
55*9d12795fSRobert Mustacchi 	while (buflen > out) {
56*9d12795fSRobert Mustacchi 		int err;
57*9d12795fSRobert Mustacchi 		size_t len = MIN(sizeof (rbytes), buflen);
58*9d12795fSRobert Mustacchi 
59*9d12795fSRobert Mustacchi 		if (flags & GRND_RANDOM) {
60*9d12795fSRobert Mustacchi 			if (flags & GRND_NONBLOCK)
61*9d12795fSRobert Mustacchi 				err = random_get_bytes(rbytes, len);
62*9d12795fSRobert Mustacchi 			else
63*9d12795fSRobert Mustacchi 				err = random_get_blocking_bytes(rbytes, len);
64*9d12795fSRobert Mustacchi 		} else {
65*9d12795fSRobert Mustacchi 			err = random_get_pseudo_bytes(rbytes, len);
66*9d12795fSRobert Mustacchi 		}
67*9d12795fSRobert Mustacchi 
68*9d12795fSRobert Mustacchi 		if (err == 0) {
69*9d12795fSRobert Mustacchi 			if (ddi_copyout(rbytes, buf + out, len, 0) != 0)
70*9d12795fSRobert Mustacchi 				return (set_errno(EFAULT));
71*9d12795fSRobert Mustacchi 			out += len;
72*9d12795fSRobert Mustacchi 		} else if (err == EAGAIN && out > 0) {
73*9d12795fSRobert Mustacchi 			break;
74*9d12795fSRobert Mustacchi 		} else {
75*9d12795fSRobert Mustacchi 			return (set_errno(err));
76*9d12795fSRobert Mustacchi 		}
77*9d12795fSRobert Mustacchi 	}
78*9d12795fSRobert Mustacchi 
79*9d12795fSRobert Mustacchi 	return (out);
80*9d12795fSRobert Mustacchi }
81