Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src-draft/trunk]: src New system call getrandom() compatible with Linux and ...



details:   https://anonhg.NetBSD.org/src-all/rev/012e3ce3d42f
branches:  trunk
changeset: 936858:012e3ce3d42f
user:      Taylor R Campbell <riastradh%NetBSD.org@localhost>
date:      Fri May 08 07:32:41 2020 +0000

description:
New system call getrandom() compatible with Linux and others.

Three ways to call:

getrandom(p, n, 0)              Blocks until full entropy.  Returns
                                up to n bytes at p, guaranteeing
                                >=256 bytes even if interrupted after
                                blocking.  getrandom(0,0,0) serves as
                                an entropy barrier: return only after
                                system is full entropy.

getrandom(p, n, GRND_INSECURE)  Never blocks.  Guarantees >=256 bytes
                                even if interrupted.  Equivalent to
                                /dev/urandom.  Safe only after
                                successful getrandom(...,0),
                                getrandom(...,GRND_RANDOM), or read
                                from /dev/random.

getrandom(p, n, GRND_RANDOM)    May block at any time.  Returns up to n
                                bytes at p, but no guarantees about how
                                many -- may return as short as 1 byte.
                                Equivalent to /dev/random.  Legacy.
                                Provided only for source compatibility
                                with Linux.

Can also use flags|GRND_NONBLOCK to fail with EWOULDBLOCK/EAGAIN
without producing any output instead of blocking.

- The combination GRND_INSECURE|GRND_NONBLOCK is the same as
  GRND_INSECURE, since GRND_INSECURE never blocks anyway.

- The combinations GRND_INSECURE|GRND_RANDOM and
  GRND_INSECURE|GRND_RANDOM|GRND_NONBLOCK are nonsensical and fail
  with EINVAL.

diffstat:

 distrib/sets/lists/comp/mi                  |    3 +
 distrib/sets/lists/debug/mi                 |    1 +
 distrib/sets/lists/tests/mi                 |    1 +
 lib/libc/sys/Makefile.inc                   |    7 +-
 lib/libc/sys/getrandom.2                    |  283 ++++++++++++++++++++++++++++
 sys/dev/random.c                            |  147 +------------
 sys/kern/files.kern                         |    1 +
 sys/kern/kern_entropy.c                     |   26 ++-
 sys/kern/sys_getrandom.c                    |  246 ++++++++++++++++++++++++
 sys/kern/syscalls.master                    |    3 +-
 sys/rump/librump/rumpkern/Makefile.rumpkern |    1 +
 sys/sys/Makefile                            |    2 +-
 sys/sys/entropy.h                           |    6 +-
 sys/sys/random.h                            |   69 ++++++
 tests/lib/libc/sys/Makefile                 |    1 +
 tests/lib/libc/sys/t_getrandom.c            |  170 ++++++++++++++++
 16 files changed, 827 insertions(+), 140 deletions(-)

diffs (truncated from 1166 to 300 lines):

diff -r 6c5bb806acc4 -r 012e3ce3d42f distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi        Sun May 10 11:06:14 2020 +0000
+++ b/distrib/sets/lists/comp/mi        Fri May 08 07:32:41 2020 +0000
@@ -3132,6 +3132,7 @@
 ./usr/include/sys/quotactl.h                   comp-c-include
 ./usr/include/sys/radioio.h                    comp-c-include
 ./usr/include/sys/radixtree.h                  comp-c-include
+./usr/include/sys/random.h                     comp-c-include
 ./usr/include/sys/ras.h                                comp-c-include
 ./usr/include/sys/rb.h                         comp-obsolete           obsolete
 ./usr/include/sys/rbtree.h                     comp-c-include
@@ -12517,6 +12518,7 @@
 ./usr/share/man/html2/getpid.html              comp-c-htmlman          html
 ./usr/share/man/html2/getppid.html             comp-c-htmlman          html
 ./usr/share/man/html2/getpriority.html         comp-c-htmlman          html
+./usr/share/man/html2/getrandom.html           comp-c-htmlman          html
 ./usr/share/man/html2/getrlimit.html           comp-c-htmlman          html
 ./usr/share/man/html2/getrusage.html           comp-c-htmlman          html
 ./usr/share/man/html2/getsid.html              comp-c-htmlman          html
@@ -20431,6 +20433,7 @@
 ./usr/share/man/man2/getpid.2                  comp-c-man              .man
 ./usr/share/man/man2/getppid.2                 comp-c-man              .man
 ./usr/share/man/man2/getpriority.2             comp-c-man              .man
+./usr/share/man/man2/getrandom.2               comp-c-man              .man
 ./usr/share/man/man2/getrlimit.2               comp-c-man              .man
 ./usr/share/man/man2/getrusage.2               comp-c-man              .man
 ./usr/share/man/man2/getsid.2                  comp-c-man              .man
diff -r 6c5bb806acc4 -r 012e3ce3d42f distrib/sets/lists/debug/mi
--- a/distrib/sets/lists/debug/mi       Sun May 10 11:06:14 2020 +0000
+++ b/distrib/sets/lists/debug/mi       Fri May 08 07:32:41 2020 +0000
@@ -2129,6 +2129,7 @@
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getitimer.debug           tests-lib-debug         debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getlogin.debug            tests-lib-debug         debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getpid.debug              tests-lib-debug         debug,atf,compattestfile
+./usr/libdata/debug/usr/tests/lib/libc/sys/t_getrandom.debug           tests-lib-debug         debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getrusage.debug           tests-lib-debug         debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getsid.debug              tests-lib-debug         debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libc/sys/t_getsockname.debug         tests-lib-debug         debug,atf,compattestfile
diff -r 6c5bb806acc4 -r 012e3ce3d42f distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Sun May 10 11:06:14 2020 +0000
+++ b/distrib/sets/lists/tests/mi       Fri May 08 07:32:41 2020 +0000
@@ -3127,6 +3127,7 @@
 ./usr/tests/lib/libc/sys/t_getitimer           tests-lib-tests         compattestfile,atf
 ./usr/tests/lib/libc/sys/t_getlogin            tests-lib-tests         compattestfile,atf
 ./usr/tests/lib/libc/sys/t_getpid              tests-lib-tests         compattestfile,atf
+./usr/tests/lib/libc/sys/t_getrandom           tests-lib-tests         compattestfile,atf
 ./usr/tests/lib/libc/sys/t_getrusage           tests-lib-tests         compattestfile,atf
 ./usr/tests/lib/libc/sys/t_getsid              tests-lib-tests         compattestfile,atf
 ./usr/tests/lib/libc/sys/t_getsockname         tests-lib-tests         compattestfile,atf
diff -r 6c5bb806acc4 -r 012e3ce3d42f lib/libc/sys/Makefile.inc
--- a/lib/libc/sys/Makefile.inc Sun May 10 11:06:14 2020 +0000
+++ b/lib/libc/sys/Makefile.inc Fri May 08 07:32:41 2020 +0000
@@ -110,7 +110,7 @@
                __fstatvfs190.S fstatat.S  __futimes50.S futimens.S \
        __getcwd.S __getdents30.S __getfh30.S __getvfsstat90.S getgroups.S\
                __getitimer50.S __getlogin.S getpeername.S getpgid.S getpgrp.S \
-               getpriority.S getrlimit.S __getrusage50.S getsid.S \
+               getpriority.S getrandom.S getrlimit.S __getrusage50.S getsid.S \
                getsockname.S getsockopt.S getsockopt2.S __gettimeofday50.S \
        ioctl.S \
        kqueue.S kqueue1.S ktrace.S \
@@ -250,8 +250,9 @@
        flock.2 fork.2 fsync.2 getcontext.2 getdents.2 \
        getfh.2 getvfsstat.2 getgid.2 getgroups.2 \
        getitimer.2 getlogin.2 getpeername.2 getpgrp.2 getpid.2 \
-       getpriority.2 getrlimit.2 getrusage.2 getsid.2 getsockname.2 \
-       getsockopt.2 gettimeofday.2 getuid.2 intro.2 ioctl.2 issetugid.2 \
+       getpriority.2 getrandom.2 getrlimit.2 getrusage.2 getsid.2 \
+       getsockname.2 getsockopt.2 gettimeofday.2 getuid.2\
+       intro.2 ioctl.2 issetugid.2 \
        kill.2 kqueue.2 ktrace.2 _ksem.2 \
        lfs_bmapv.2 lfs_markv.2 lfs_segclean.2 lfs_segwait.2 \
        link.2 listen.2 lseek.2 \
diff -r 6c5bb806acc4 -r 012e3ce3d42f lib/libc/sys/getrandom.2
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libc/sys/getrandom.2  Fri May 08 07:32:41 2020 +0000
@@ -0,0 +1,283 @@
+.\"    $NetBSD$
+.\"
+.\" Copyright (c) 2020 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Taylor R. Campbell.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd January 13, 2020
+.Dt GETRANDOM 2
+.Os
+.Sh NAME
+.Nm getrandom
+.Nd random number generation from system entropy
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/random.h
+.Ft ssize_t
+.Fn getrandom "void *buf" "size_t buflen" "unsigned int flags"
+.Sh DESCRIPTION
+The
+.Nm
+function fills
+.Fa buf
+with up to
+.Fa buflen
+independent uniform random bytes derived from the system's entropy
+pool.
+.Pp
+The function may block until the system has full entropy, meaning that
+the system has observed enough noise from physical processes that an
+adversary cannot predict what state it is in:
+.Bl -bullet -compact
+.It
+When the system has only partial entropy, the output of
+.Fn getrandom
+may be predictable.
+.It
+When the system has full entropy, the output is fit for use as
+cryptographic key material.
+.El
+.Pp
+The
+.Fa flags
+argument may be:
+.Bl -tag -offset abcd -width GRND_INSECURE
+.It Li 0
+Block until the system entropy pool has full entropy; then generate
+arbitrarily much data.
+.Em Recommended .
+.Pp
+If interrupted by a signal, may fail with
+.Er EINTR
+or return a short read.
+If successful, guaranteed to return at least 256 bytes even if
+interrupted.
+.It Dv GRND_INSECURE
+Do not block; instead fill
+.Fa buf
+with output derived from whatever is in the system entropy pool so
+far.
+Equivalent to reading from
+.Pa /dev/urandom ;
+see
+.Xr rnd 4 .
+.Pp
+If interrupted by a signal, may fail with
+.Er EINTR
+or return a short read.
+If successful, guaranteed to return at least 256 bytes even if
+interrupted.
+.Pp
+Despite the name, this is secure as long as you only do it
+.Em after
+at least one successful call without
+.Dv GRND_INSECURE ,
+such as
+.Li "getrandom(..., 0)"
+or
+.Li "getrandom(..., GRND_RANDOM)" ,
+or after reading at least one byte from
+.Pa /dev/random .
+.Pp
+.Sy WARNING :
+If you use
+.Dv GRND_INSECURE
+.Em before
+the system has full entropy. the output may enable an adversary to
+search the possible states of the entropy pool by brute force, and
+thereby reduce its entropy to zero.
+Thus, incautious use of
+.Dv GRND_INSECURE
+can ruin the security of the whole system.
+.Pp
+.Nx
+attempts to defend against this threat model by resetting the system's
+entropy estimate to zero in this event, requiring gathering full
+entropy again before
+.Pa /dev/random
+or
+.Fn getrandom
+without
+.Dv GRND_INSECURE
+will unblock, but other operating systems may not.
+.It Dv GRND_RANDOM
+Block until the system entropy pool has full entropy; then generate a
+small amount of data.
+Equivalent to reading from
+.Pa /dev/random ;
+see
+.Xr rnd 4 .
+This is provided mainly for source compatibility with Linux; there is
+essentially no reason to ever use it.
+.El
+.Pp
+The flag
+.Dv GNRD_NONBLOCK
+may also be included with bitwise-OR, in which case if
+.Fn getrandom
+would have blocked without
+.Dv GRND_NONBLOCK ,
+it returns
+.Er EAGAIN
+instead.
+.Pp
+Adding
+.Dv GRND_NONBLOCK
+to
+.Dv GRND_INSECURE
+has no effect; the combination
+.Dv GRND_INSECURE Ns Li "|" Ns Li GRND_NONBLOCK
+is equivalent to
+.Dv GRND_INSECURE ,
+since
+.Dv GRND_INSECURE
+never blocks.
+The combination
+.Dv GRND_INSECURE Ns Li "|" Ns Li GRND_RANDOM
+is nonsensical and fails with
+.Er EINVAL .
+.Sh RETURN VALUES
+If successful,
+.Fn getrandom
+returns the number of bytes stored in
+.Fa buf .
+Otherwise,
+.Fn getrandom
+returns \-1 and sets
+.Va errno .
+.Pp
+Since
+.Li "getrandom(..., 0)"
+and
+.Li "getrandom(..., GRND_INSECURE)"
+are guaranteed to return at least 256 bytes if successful, it
+is sufficient to use, e.g.,
+.Bd -literal -compact
+       getrandom(buf, 32, 0) == -1
+.Ed
+or
+.Bd -literal -compact
+       getrandom(buf, 32, GRND_INSECURE) == -1
+.Ed
+to detect failure.
+However, with
+.Dv GRND_RANDOM ,
+.Fn getrandom
+may return as little as a single byte if successful.
+.Sh EXAMPLES
+.Sy Recommended usage .
+Generate a key for cryptography:
+.Bd -literal
+       uint8_t secretkey[32];
+
+       if (getrandom(secretkey, sizeof secretkey, 0) == -1)
+               err(EXIT_FAILURE, "getrandom");
+       crypto_secretbox_xsalsa20poly1305(..., secretkey);
+.Ed
+.Pp
+Other idioms for illustration:
+.Bl -bullet
+.It
+Wait for entropy once, and then generate many keys without waiting:
+.Bd -literal
+       struct { uint8_t key[32]; } user[100];
+
+       if (getrandom(NULL, 0, 0) == -1)
+               err(EXIT_FAILURE, "getrandom");
+       for (i = 0; i < 100; i++)
+               if (getrandom(user[i].key, sizeof user[i].key,
+                   GRND_INSECURE) == -1)
+                       err(EXIT_FAILURE, "getrandom");
+.Ed
+.It
+Twiddle thumbs while waiting for entropy:
+.Bd -literal
+       uint8_t secretkey[32];
+
+       while (getrandom(secretkey, sizeof secretkey, GRND_NONBLOCK)
+           == -1) {
+               if (errno != EAGAIN)



Home | Main Index | Thread Index | Old Index