From dc45c4d4ea09452003e772d03e8d7a26975a05e9 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Thu, 30 Jan 2020 13:12:25 -0700 Subject: [PATCH] Add tests for arc4random_buf() and an implementation for those without. --- MANIFEST | 1 + config.h.in | 3 ++ configure | 32 ++++++++++++++++++ configure.ac | 5 +++ include/sudo_rand.h | 6 ++++ lib/util/arc4random.c | 4 --- lib/util/arc4random_buf.c | 69 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 lib/util/arc4random_buf.c diff --git a/MANIFEST b/MANIFEST index c927c5cc4..2a58f6fa6 100644 --- a/MANIFEST +++ b/MANIFEST @@ -110,6 +110,7 @@ lib/logsrv/protobuf-c.c lib/util/Makefile.in lib/util/aix.c lib/util/arc4random.c +lib/util/arc4random_buf.c lib/util/arc4random_uniform.c lib/util/cfmakeraw.c lib/util/chacha_private.h diff --git a/config.h.in b/config.h.in index 54b9e4a34..cd7f677cd 100644 --- a/config.h.in +++ b/config.h.in @@ -54,6 +54,9 @@ /* Define to 1 if you have the `arc4random' function. */ #undef HAVE_ARC4RANDOM +/* Define to 1 if you have the `arc4random_buf' function. */ +#undef HAVE_ARC4RANDOM_BUF + /* Define to 1 if you have the `arc4random_uniform' function. */ #undef HAVE_ARC4RANDOM_UNIFORM diff --git a/configure b/configure index 8ad6fd7c2..15464bb47 100755 --- a/configure +++ b/configure @@ -19911,6 +19911,32 @@ esac done +fi +done + + for ac_func in arc4random_buf +do : + ac_fn_c_check_func "$LINENO" "arc4random_buf" "ac_cv_func_arc4random_buf" +if test "x$ac_cv_func_arc4random_buf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ARC4RANDOM_BUF 1 +_ACEOF + +else + + case " $LIBOBJS " in + *" arc4random_buf.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS arc4random_buf.$ac_objext" + ;; +esac + + + for _sym in sudo_arc4random_buf; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + fi done @@ -19929,6 +19955,12 @@ esac " done + + for _sym in sudo_arc4random_buf; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + case " $LIBOBJS " in *" arc4random_uniform.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS arc4random_uniform.$ac_objext" diff --git a/configure.ac b/configure.ac index e9822a22f..792891b78 100644 --- a/configure.ac +++ b/configure.ac @@ -2637,9 +2637,14 @@ AC_CHECK_FUNCS([arc4random], [ AC_LIBOBJ(arc4random_uniform) SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform) ]) + AC_CHECK_FUNCS([arc4random_buf], [], [ + AC_LIBOBJ(arc4random_buf) + SUDO_APPEND_COMPAT_EXP(sudo_arc4random_buf) + ]) ], [ AC_LIBOBJ(arc4random) SUDO_APPEND_COMPAT_EXP(sudo_arc4random) + SUDO_APPEND_COMPAT_EXP(sudo_arc4random_buf) AC_LIBOBJ(arc4random_uniform) SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform) # arc4random.c needs getentropy() diff --git a/include/sudo_rand.h b/include/sudo_rand.h index 49c75ec0c..bb7d36596 100644 --- a/include/sudo_rand.h +++ b/include/sudo_rand.h @@ -35,6 +35,12 @@ __dso_public uint32_t sudo_arc4random(void); # define arc4random() sudo_arc4random() #endif /* ARC4RANDOM */ +#ifndef HAVE_ARC4RANDOM_BUF +__dso_public void sudo_arc4random_buf(void *buf, size_t n); +# undef arc4random_buf +# define arc4random_buf(a, b) sudo_arc4random_buf((a), (b)) +#endif /* ARC4RANDOM_BUF */ + #ifndef HAVE_ARC4RANDOM_UNIFORM __dso_public uint32_t sudo_arc4random_uniform(uint32_t upper_bound); # undef arc4random_uniform diff --git a/lib/util/arc4random.c b/lib/util/arc4random.c index efe6a2455..15fc9a0b3 100644 --- a/lib/util/arc4random.c +++ b/lib/util/arc4random.c @@ -148,7 +148,6 @@ _rs_rekey(unsigned char *dat, size_t datlen) rs_have = sizeof(rs_buf) - KEYSZ - IVSZ; } -#ifdef notdef static inline void _rs_random_buf(void *_buf, size_t n) { @@ -171,7 +170,6 @@ _rs_random_buf(void *_buf, size_t n) _rs_rekey(NULL, 0); } } -#endif static inline void _rs_random_u32(uint32_t *val) @@ -198,7 +196,6 @@ sudo_arc4random(void) return val; } -#ifdef notdef void sudo_arc4random_buf(void *buf, size_t n) { @@ -206,6 +203,5 @@ sudo_arc4random_buf(void *buf, size_t n) _rs_random_buf(buf, n); _ARC4_UNLOCK(); } -#endif #endif /* HAVE_ARC4RANDOM */ diff --git a/lib/util/arc4random_buf.c b/lib/util/arc4random_buf.c new file mode 100644 index 000000000..41ddc1d29 --- /dev/null +++ b/lib/util/arc4random_buf.c @@ -0,0 +1,69 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2020 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is an open source non-commercial project. Dear PVS-Studio, please check it. + * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + */ + +#include + +#ifndef HAVE_ARC4RANDOM_BUF + +#include +#include +#if defined(HAVE_STDINT_H) +# include +#elif defined(HAVE_INTTYPES_H) +# include +#endif + +#include "sudo_compat.h" +#include "sudo_rand.h" + +/* + * Call arc4random() repeatedly to fill buf with n bytes of random data. + */ +void +sudo_arc4random_buf(void *buf, size_t n) +{ + char *cp = buf; + + while (n != 0) { + size_t m = minimum(n, 4); + uint32_t val = arc4random(); + + switch (m) { + case 4: + *cp++ = (val >> 24) & 0xff; + /* FALLTHROUGH */ + case 3: + *cp++ = (val >> 16) & 0xff; + /* FALLTHROUGH */ + case 2: + *cp++ = (val >> 8) & 0xff; + /* FALLTHROUGH */ + case 1: + *cp++ = val & 0xff; + break; + } + n -= m; + } +} + +#endif /* HAVE_ARC4RANDOM_BUF */