1.\" $NetBSD: rnd.9,v 1.33 2024/12/25 17:51:56 andvar Exp $ 2.\" 3.\" Copyright (c) 1997 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This documentation is derived from text contributed to The NetBSD 7.\" Foundation by S.P.Zeidler (aka stargazer). 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" POSSIBILITY OF SUCH DAMAGE. 29.\" 30.Dd April 25, 2020 31.Dt RND 9 32.Os 33.Sh NAME 34.Nm RND , 35.Nm rnd_attach_source , 36.Nm rnd_detach_source , 37.Nm rnd_add_data , 38.Nm rnd_add_data_intr , 39.Nm rnd_add_data_sync , 40.Nm rnd_add_uint32 41.Nd functions to make a device available for entropy collection 42.Sh SYNOPSIS 43.In sys/rndsource.h 44.Vt typedef struct krndsource krndsource_t; 45.Ft void 46.Fn rndsource_setcb "krndsource_t *rnd_source" "void (*callback)(size_t, void *)" "void *cookie" 47.Ft void 48.Fn rnd_attach_source "krndsource_t *rnd_source" "char *devname" "uint32_t source_type" "uint32_t flags" 49.Ft void 50.Fn rnd_detach_source "krndsource_t *rnd_source" 51.Ft void 52.Fn rnd_add_data "krndsource_t *rnd_source" "void *data" "uint32_t len" "uint32_t entropy" 53.Ft void 54.Fn rnd_add_data_intr "krndsource_t *rnd_source" "void *data" "uint32_t len" "uint32_t entropy" 55.Ft void 56.Fn rnd_add_data_sync "krndsource_t *rnd_source" "void *data" "uint32_t len" "uint32_t entropy" 57.Ft void 58.Fn rnd_add_uint32 "krndsource_t *rnd_source" "uint32_t datum" 59.Sh DESCRIPTION 60The 61.Nm 62functions enable drivers to collect samples of physical observations, 63such as network packet timings or hardware random number generator 64outputs, into a kernel entropy pool to derive key material for 65.Xr cprng 9 66and 67.Xr rnd 4 68.Pq Pa /dev/random , Pa /dev/urandom . 69.Pp 70Usage model: 71.Bl -enum -compact 72.It 73Allocate and zero a 74.Vt struct krndsource 75object before using the 76.Nm 77functions. 78.It 79Optionally, set a callback with 80.Fn rndsource_setcb 81if appropriate, e.g. for an on-demand hardware random number 82generator. 83.It 84Attach the random source with 85.Fn rnd_attach_source . 86.It 87Enter data with 88.Fn rnd_add_data , 89.Fn rnd_add_data_intr , 90or 91.Fn rnd_add_uint32 , 92or, if in the callback, 93.Fn rnd_add_data_sync . 94.It 95When the driver is done, detach it with 96.Fn rnd_detach_source . 97.El 98.Pp 99The following types of random sources are defined: 100.Bl -tag -width "Dv RND_TYPE_UNKNOWN" -compact 101.It Dv RND_TYPE_DISK 102Disk devices, typically sampling seek timings. 103.It Dv RND_TYPE_ENV 104Environmental sensors. 105.It Dv RND_TYPE_POWER 106Power sensors and timing of power-related events. 107.It Dv RND_TYPE_NET 108Network interfaces, typically sampling packet timings. 109By default, sample from network interfaces are ignored, for hysterical 110raisins. 111.It Dv RND_TYPE_RNG 112Hardware random number generators. 113.It Dv RND_TYPE_SKEW 114Skew between clocks. 115.It Dv RND_TYPE_TAPE 116Tape devices, typically sampling I/O timings. 117.It Dv RND_TYPE_TTY 118Tty devices, typically sampling interrupt timings. 119.It Dv RND_TYPE_VM 120Virtual memory fault timings. 121.It Dv RND_TYPE_UNKNOWN 122Unknown sources, or sources not otherwise classified. 123.El 124.Sh FUNCTIONS 125.Bl -tag -width abcd 126.It Fn rndsource_setcb "rnd_source" "callback" "cookie" 127Sets a callback to be invoked when the entropy pool is hungry 128to draw data from this source on demand. 129Optional; if used, must be used 130.Em before 131.Fn rnd_attach_source , 132and the caller must pass 133.Dv RND_FLAG_HASCB 134to 135.Fn rnd_attach_source . 136.Pp 137The callback is invoked as 138.Fo callback 139.Fa nbytes 140.Fa cookie 141.Fc , 142where 143.Fa nbytes 144is the number of bytes requested for the entropy pool, and 145.Fa cookie 146is the cookie that was passed to 147.Fn rndsource_setcb . 148The callback normally does one of two things: 149.Bl -dash 150.It 151Sends a request to a hardware device for entropy and returns. 152The hardware will later return data asynchronously by an interrupt, and 153the callback will use 154.Fn rnd_add_data , 155.Fn rnd_add_data_intr , 156or 157.Fn rnd_add_uint32 158to add the data to the pool. 159.It 160Synchronously gathers entropy from hardware \(em for example, by a CPU 161instruction like Intel RDSEED. 162In this case, in order to add data to the pool 163.Em before 164returning, the callback 165.Em must 166use 167.Fn rnd_add_data_sync , 168not 169.Fn rnd_add_data , 170.Fn rnd_add_data_intr \" this works for now but no promises 171or 172.Fn rnd_add_uint32 . \" this also works for now but no promises 173.El 174.Pp 175.Nm 176issues calls to each source's 177.Fa callback 178in serial \(em it never issues two calls to the same source's callback 179at the same time in two different threads or on two different CPUs. 180.Pp 181The callback may be invoked in thread context or soft interrupt 182context, up to 183.Dv SOFTINT_SERIAL , 184and as such must follow the rules of soft interrupt handlers in 185.Xr softint 9 186\(em that is, the callback must never sleep, except on adaptive 187.Xr mutex 9 188locks at 189.Dv IPL_SOFTSERIAL . 190The callback will never be called in hard interrupt context. 191.It Fn rnd_attach_source "rnd_source" "devname" "type" "flags" 192Makes 193.Fa rnd_source 194available for entropy collection. 195Must be called 196.Em before 197the source struct pointed to by 198.Fa rnd_source 199is used in any of the following functions. 200If a callback was specified with 201.Fn rndsource_setcb , 202the kernel may invoke it at any time after 203.Fn rnd_attach_source 204until 205.Fn rnd_detach_source , 206so the callback must be ready to be invoked 207.Em before 208calling 209.Fn rnd_attach_source . 210.Pp 211The 212.Fa devname 213is exposed via 214.Xr rnd 4 215and 216.Xr rndctl 8 . 217The 218.Fa type 219must be one of the 220.Dv RND_TYPE_* 221constants above. 222The 223.Fa flags 224are the bitwise-or of any of the following constants: 225.Bl -tag -width abcd 226.It Dv RND_FLAG_HASCB 227The random source has a callback, which must have been set with 228.Fn rndsource_setcb . 229.It Dv RND_FLAG_COLLECT_TIME 230Enter the timing of each 231.Fn rnd_add_* 232call into the entropy pool. 233If not set, at most only the data arguments to 234.Fn rnd_add_* 235will be entered. 236.It Dv RND_FLAG_COLLECT_VALUE 237Enter the data arguments passed to the 238.Fn rnd_add_* 239functions into the pool. 240If not set, the data will be ignored; at most the timing of the sample 241will be entered. 242.It Dv RND_FLAG_DEFAULT 243Equivalent to 244.Dv RND_FLAG_COLLECT_TIME | RND_FLAG_COLLECT_VALUE . 245.It Dv RND_FLAG_ESTIMATE_TIME , RND_FLAG_ESTIMATE_VALUE 246Legacy options no longer used. 247.El 248.It Fn rnd_detach_source "rnd_source" 249Disconnects 250.Fa rnd_source 251from entropy collection. 252The kernel will cease to invoke the callback, if any, and the caller 253must not use 254.Fa rnd_source 255with any of the 256.Fn rnd_add_* 257functions after 258.Fn rnd_detach_source . 259The caller may release the memory for 260.Fa rnd_source 261afterward. 262.It Fn rnd_add_data "rnd_source" "data" "len" "entropy" 263Enters 264.Fa len 265bytes at 266.Fa data 267into the entropy pool, if 268.Dv RND_FLAG_COLLECT_VALUE 269was specified for 270.Fa rnd_source , 271and a timestamp, if 272.Dv RND_FLAG_COLLECT_TIME 273was specified. 274.Pp 275The argument 276.Fa entropy 277provides a conservative estimate for the number of bits of entropy in 278the 279.Em physical process 280that generated the data, given all the past samples. 281Drivers for devices for which this is not known should pass zero; 282typically only drivers for hardware random number generators pass 283nonzero values. 284Hardware random number generator drivers should perform on-line 285self-tests before advertising nonzero entropy for samples. 286.Pp 287.Fn rnd_add_data 288.Em must not 289be used during a callback as set with 290.Fn rndsource_setcb ; 291use 292.Fn rnd_add_data_sync 293instead. 294.Pp 295.Fn rnd_add_data 296.Em must not 297be called from thread context with spin locks held. 298.Pp 299For compatibility, 300.Fn rnd_add_data 301currently 302.Em may 303but 304.Em should not 305be called from interrupt context, possibly with spin locks held. 306However, this may be forbidden in the future; use 307.Fn rnd_add_data_intr 308from interrupt context instead, if the work can't be usefully deferred 309to softint or thread. 310.It Fn rnd_add_data_intr "rnd_source" "data" "len" "entropy" 311Tries to enter 312.Fa len 313bytes at 314.Fa data 315into the entropy pool like 316.Fn rnd_add_data , 317but if this fills or would overflow a sample buffer, schedules a 318softint to process it and discards an unspecified subset of the data 319while counting zero entropy for the sample. 320.Pp 321.Fn rnd_add_data_intr 322may be called from any context, including hard interrupt context, 323including contexts where spin locks are held, except that it 324.Em must not 325be used during a callback as set with 326.Fn rndsource_setcb ; 327use 328.Fn rnd_add_data_sync 329in that context instead. 330.It Fn rnd_add_data_sync "rnd_source" "data" "len" "entropy" 331Like 332.Fn rnd_add_data , 333but may be used in a callback as set with 334.Fn rndsource_setcb . 335Must always be called in thread context. 336.It Fn rnd_add_uint32 "rnd_source" "datum" 337Equivalent to 338.Li rnd_add_data_intr Ns ( Ns Fa rnd_source , Li & Ns Fa datum , Li 4 , 0 ) . 339.Pp 340.Fn rnd_add_uint32 341may be called from any context, including hard interrupt context, 342including contexts where spin locks are held, except that it 343.Em must not 344be used during a callback as set with 345.Fn rndsource_setcb ; 346use 347.Fn rnd_add_data_sync 348in that context instead. 349.Pp 350.Fn rnd_add_uint32 351is meant for cheaply taking samples from devices that aren't designed 352to be hardware random number generators. 353.El 354.Sh FILES 355These functions are declared in src/sys/sys/rndsource.h and defined in 356src/sys/kern/kern_entropy.c. 357.Sh EXAMPLES 358.Bd -literal 359struct xyz_softc { 360 ... 361 struct krndsource sc_rndsource; 362}; 363 364static void 365xyz_attach(device_t parent, device_t self, void *aux) 366{ 367 struct xyz_softc *sc = device_private(self); 368 ... 369 rndsource_setcb(&sc->sc_rndsource, xyz_get, sc); 370 rnd_attach_source(&sc->sc_rndsource, device_xname(self), 371 RND_TYPE_RNG, RND_FLAG_DEFAULT); 372} 373 374static int 375xyz_detach(device_t self, int flags) 376{ 377 ... 378 rnd_detach_source(&sc->sc_rndsource); 379 ... 380 return 0; 381} 382 383static void 384xyz_get(size_t nbytes, void *cookie) 385{ 386 struct xyz_softc *sc = cookie; 387 uint32_t v; 388 unsigned timo = 10; 389 390 while (nbytes) { 391 while (bus_space_read_4(sc->sc_bst, sc->sc_bsh, 392 XYZ_RNGREADY) == 0) { 393 if (--timo == 0) 394 return; 395 DELAY(10); 396 } 397 v = bus_space_read_4(sc->sc_bst, sc->sc_bsh, 398 XYZ_RNGDATUM); 399 /* data sheet sez 18 bits entropy in 32-bit sample */ 400 rnd_add_data_sync(&sc->sc_rndsource, &v, sizeof v, 18); 401 nbytes -= 18/NBBY; 402 } 403} 404 405static void 406xyz_intr(void *cookie) 407{ 408 struct xyz_softc *sc = cookie; 409 uint32_t isr; 410 411 isr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, XYZ_ISR); 412 bus_space_write_4(sc->sc_bst, sc->sc_bsh, XYZ_ISR, isr); 413 rnd_add_uint32(&sc->sc_rndsource, isr); 414 ... 415} 416.Ed 417.Sh SEE ALSO 418.Xr rnd 4 , 419.Xr rndctl 8 , 420.Xr cprng 9 421.Sh HISTORY 422The random device was introduced in 423.Nx 1.3 . 424It was substantially rewritten in 425.Nx 6.0 , 426and again in 427.Nx 10.0 . 428.Sh AUTHORS 429This implementation was written by 430.An Taylor R Campbell Aq Mt riastradh@NetBSD.org . 431