Source-Changes-HG archive

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

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



details:   https://anonhg.NetBSD.org/src/rev/1fc2113fd71f
branches:  trunk
changeset: 937260:1fc2113fd71f
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Aug 14 00:53:15 2020 +0000

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

Three ways to call:

getrandom(p, n, 0)              Blocks at boot until full entropy.
                                Returns up to n bytes at p; guarantees
                                up to 256 bytes even if interrupted
                                after blocking.  getrandom(0,0,0)
                                serves as an entropy barrier: return
                                only after system has full entropy.

getrandom(p, n, GRND_INSECURE)  Never blocks.  Guarantees up to 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.

As proposed on tech-userlevel, tech-crypto, tech-security, and
tech-kern, and subsequently adopted by core (minus the getentropy part
of the proposal, because other operating systems and participants in
the discussion couldn't come to an agreement about getentropy and
blocking semantics):

https://mail-index.netbsd.org/tech-userlevel/2020/05/02/msg012333.html

diffstat:

 distrib/sets/lists/comp/mi                  |    5 +-
 distrib/sets/lists/debug/mi                 |    3 +-
 distrib/sets/lists/tests/mi                 |    3 +-
 lib/libc/sys/Makefile.inc                   |    9 +-
 lib/libc/sys/getrandom.2                    |  283 ++++++++++++++++++++++++++++
 sys/dev/random.c                            |  151 +-------------
 sys/kern/files.kern                         |    3 +-
 sys/kern/kern_entropy.c                     |   30 ++-
 sys/kern/sys_getrandom.c                    |  246 ++++++++++++++++++++++++
 sys/kern/syscalls.master                    |    5 +-
 sys/rump/librump/rumpkern/Makefile.rumpkern |    3 +-
 sys/sys/Makefile                            |    4 +-
 sys/sys/entropy.h                           |    8 +-
 sys/sys/random.h                            |   69 ++++++
 tests/lib/libc/sys/Makefile                 |    3 +-
 tests/lib/libc/sys/t_getrandom.c            |  170 ++++++++++++++++
 16 files changed, 841 insertions(+), 154 deletions(-)

diffs (truncated from 1256 to 300 lines):

diff -r 22d783307a64 -r 1fc2113fd71f distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi        Thu Aug 13 20:13:46 2020 +0000
+++ b/distrib/sets/lists/comp/mi        Fri Aug 14 00:53:15 2020 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: mi,v 1.2342 2020/08/11 13:19:15 christos Exp $
+#      $NetBSD: mi,v 1.2343 2020/08/14 00:53:15 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 ./etc/mtree/set.comp                           comp-sys-root
@@ -3137,6 +3137,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
@@ -12742,6 +12743,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
@@ -20862,6 +20864,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 22d783307a64 -r 1fc2113fd71f distrib/sets/lists/debug/mi
--- a/distrib/sets/lists/debug/mi       Thu Aug 13 20:13:46 2020 +0000
+++ b/distrib/sets/lists/debug/mi       Fri Aug 14 00:53:15 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.326 2020/07/25 22:53:38 riastradh Exp $
+# $NetBSD: mi,v 1.327 2020/08/14 00:53:16 riastradh Exp $
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib                                      comp-sys-usr            compatdir
 ./usr/lib/i18n/libBIG5_g.a                     comp-c-debuglib         debuglib,compatfile
@@ -2141,6 +2141,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 22d783307a64 -r 1fc2113fd71f distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Thu Aug 13 20:13:46 2020 +0000
+++ b/distrib/sets/lists/tests/mi       Fri Aug 14 00:53:15 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.888 2020/08/09 16:32:28 rillig Exp $
+# $NetBSD: mi,v 1.889 2020/08/14 00:53:16 riastradh Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -3142,6 +3142,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 22d783307a64 -r 1fc2113fd71f lib/libc/sys/Makefile.inc
--- a/lib/libc/sys/Makefile.inc Thu Aug 13 20:13:46 2020 +0000
+++ b/lib/libc/sys/Makefile.inc Fri Aug 14 00:53:15 2020 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile.inc,v 1.244 2020/07/17 15:34:17 kamil Exp $
+#      $NetBSD: Makefile.inc,v 1.245 2020/08/14 00:53:16 riastradh Exp $
 #      @(#)Makefile.inc        8.3 (Berkeley) 10/24/94
 
 # sys sources
@@ -115,7 +115,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 \
@@ -256,8 +256,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 22d783307a64 -r 1fc2113fd71f lib/libc/sys/getrandom.2
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libc/sys/getrandom.2  Fri Aug 14 00:53:15 2020 +0000
@@ -0,0 +1,283 @@
+.\"    $NetBSD: getrandom.2,v 1.1 2020/08/14 00:53:16 riastradh Exp $
+.\"
+.\" 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);



Home | Main Index | Thread Index | Old Index