From 1c00b1a3fd12fb26d7f9f51127507acc7d870afd Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Fri, 25 Oct 2024 18:09:30 +0800 Subject: [PATCH] libc: Refine the arc4random_buf implementation fill the buffer with getrandom instead random pool and move the implementation to from crypto to libc Signed-off-by: Xiang Xiao --- crypto/random_pool.c | 35 +------- drivers/crypto/dev_urandom.c | 3 +- drivers/vhost/vhost-rng.c | 9 +- include/nuttx/random.h | 10 +++ include/stdlib.h | 2 - include/sys/syscall_lookup.h | 8 -- libs/libc/libc.csv | 2 + libs/libc/stdlib/CMakeLists.txt | 1 + libs/libc/stdlib/Make.defs | 2 +- .../libc/stdlib/lib_arc4random.c | 83 ++++++++++++++++--- libs/libc/unistd/lib_getentropy.c | 22 +---- libs/libc/uuid/lib_uuid_create.c | 48 +---------- net/tcp/tcp_seqno.c | 6 +- net/utils/CMakeLists.txt | 1 - net/utils/Make.defs | 4 +- net/utils/utils.h | 20 +---- syscall/syscall.csv | 1 - 17 files changed, 103 insertions(+), 154 deletions(-) rename net/utils/net_getrandom.c => libs/libc/stdlib/lib_arc4random.c (54%) diff --git a/crypto/random_pool.c b/crypto/random_pool.c index cdbcb0df4c95b..802c5bf80d07d 100644 --- a/crypto/random_pool.c +++ b/crypto/random_pool.c @@ -508,15 +508,10 @@ void up_randompool_initialize(void) } /**************************************************************************** - * Name: arc4random_buf + * Name: up_rngbuf * * Description: - * Fill a buffer of arbitrary length with randomness. This is the - * preferred interface for getting random numbers. The traditional - * /dev/random approach is susceptible for things like the attacker - * exhausting file descriptors on purpose. - * - * Note that this function cannot fail, other than by asserting. + * Fill a buffer of arbitrary length with randomness. * * Input Parameters: * bytes - Buffer for returned random bytes @@ -527,33 +522,9 @@ void up_randompool_initialize(void) * ****************************************************************************/ -void arc4random_buf(FAR void *bytes, size_t nbytes) +void up_rngbuf(FAR void *bytes, size_t nbytes) { nxmutex_lock(&g_rng.rd_lock); rng_buf_internal(bytes, nbytes); nxmutex_unlock(&g_rng.rd_lock); } - -/**************************************************************************** - * Name: arc4random - * - * Description: - * Returns a single 32-bit value. This is the preferred interface for - * getting random numbers. The traditional /dev/random approach is - * susceptible for things like the attacker exhausting file - * descriptors on purpose. - * - * Note that this function cannot fail, other than by asserting. - * - * Returned Value: - * a random 32-bit value. - * - ****************************************************************************/ - -uint32_t arc4random(void) -{ - uint32_t ret; - - arc4random_buf(&ret, sizeof(ret)); - return ret; -} diff --git a/drivers/crypto/dev_urandom.c b/drivers/crypto/dev_urandom.c index 9ead0dd27ae91..cb9f5cd8adee8 100644 --- a/drivers/crypto/dev_urandom.c +++ b/drivers/crypto/dev_urandom.c @@ -148,9 +148,8 @@ static ssize_t devurand_read(FAR struct file *filep, FAR char *buffer, #ifdef CONFIG_DEV_URANDOM_RANDOM_POOL if (len > 0) { - arc4random_buf(buffer, len); + up_rngbuf(buffer, len); } - #else size_t n; uint32_t rnd; diff --git a/drivers/vhost/vhost-rng.c b/drivers/vhost/vhost-rng.c index 8a8b1be7daa8f..057c748223d5e 100644 --- a/drivers/vhost/vhost-rng.c +++ b/drivers/vhost/vhost-rng.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -99,12 +99,7 @@ static void vhost_rng_work(FAR void *arg) } spin_unlock_irqrestore(&priv->lock, flags); - ret = getrandom(buf, len, 0); - if (ret < 0) - { - vhosterr("getrandom failed, ret=%zd\n", ret); - ret = 0; - } + arc4random_buf(buf, len); flags = spin_lock_irqsave(&priv->lock); virtqueue_add_consumed_buffer(vq, idx, (uint32_t)ret); diff --git a/include/nuttx/random.h b/include/nuttx/random.h index 8f56581f7bc1b..e60f58fe5f597 100644 --- a/include/nuttx/random.h +++ b/include/nuttx/random.h @@ -131,6 +131,16 @@ void up_rngaddint(enum rnd_source_t kindof, int val); void up_rngaddentropy(enum rnd_source_t kindof, FAR const uint32_t *buf, size_t n); +/**************************************************************************** + * Name: up_rngbuf + * + * Description: + * Fill a buffer of arbitrary length with randomness. + * + ****************************************************************************/ + +void up_rngbuf(FAR void *bytes, size_t nbytes); + /**************************************************************************** * Name: up_rngreseed * diff --git a/include/stdlib.h b/include/stdlib.h index 0df2efa0d2aac..b5a5b3028584c 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -152,10 +152,8 @@ double erand48(FAR unsigned short int xsubi[3]); #define srandom(s) srand(s) long random(void); -#ifdef CONFIG_CRYPTO_RANDOM_POOL void arc4random_buf(FAR void *bytes, size_t nbytes); uint32_t arc4random(void); -#endif /* Environment variable support */ diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 18438e195f345..8e27edae0071d 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -384,14 +384,6 @@ SYSCALL_LOOKUP(munmap, 2) SYSCALL_LOOKUP(socketpair, 4) #endif -/* The following is defined only if entropy pool random number generator - * is enabled. - */ - -#ifdef CONFIG_CRYPTO_RANDOM_POOL - SYSCALL_LOOKUP(arc4random_buf, 2) -#endif - SYSCALL_LOOKUP(nanosleep, 2) /* I/O event notification facility */ diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index 3f79adab535ca..49865e8ff155c 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -14,6 +14,8 @@ "aio_suspend","aio.h","defined(CONFIG_FS_AIO)","int","FAR const struct aiocb * const []|FAR const struct aiocb * const *","int","FAR const struct timespec *" "alarm","unistd.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","unsigned int","unsigned int" "alphasort","dirent.h","","int","FAR const struct dirent **","FAR const struct dirent **" +"arc4random","stdlib.h","","uint32_t" +"arc4random_buf","stdlib.h","","void","FAR void *","size_t" "asprintf","stdio.h","","int","FAR char **","FAR const IPTR char *","..." "atof","stdlib.h","defined(CONFIG_HAVE_DOUBLE)","double","FAR const char *" "atoi","stdlib.h","","int","FAR const char *" diff --git a/libs/libc/stdlib/CMakeLists.txt b/libs/libc/stdlib/CMakeLists.txt index a0cde9ee2898c..39ee2a80007c9 100644 --- a/libs/libc/stdlib/CMakeLists.txt +++ b/libs/libc/stdlib/CMakeLists.txt @@ -61,6 +61,7 @@ set(SRCS lib_wctomb.c lib_mbstowcs.c lib_wcstombs.c + lib_arc4random.c lib_atexit.c) if(CONFIG_PSEUDOTERM) diff --git a/libs/libc/stdlib/Make.defs b/libs/libc/stdlib/Make.defs index 3294bfdc36e80..22b57ccf0e236 100644 --- a/libs/libc/stdlib/Make.defs +++ b/libs/libc/stdlib/Make.defs @@ -30,7 +30,7 @@ CSRCS += lib_strtoll.c lib_strtoul.c lib_strtoull.c lib_strtold.c CSRCS += lib_checkbase.c lib_mktemp.c lib_mkstemp.c lib_mkdtemp.c CSRCS += lib_aligned_alloc.c lib_posix_memalign.c lib_valloc.c lib_mblen.c CSRCS += lib_mbtowc.c lib_wctomb.c lib_mbstowcs.c lib_wcstombs.c lib_atexit.c -CSRCS += lib_reallocarray.c +CSRCS += lib_reallocarray.c lib_arc4random.c ifeq ($(CONFIG_PSEUDOTERM),y) CSRCS += lib_ptsname.c lib_ptsnamer.c lib_unlockpt.c lib_openpty.c diff --git a/net/utils/net_getrandom.c b/libs/libc/stdlib/lib_arc4random.c similarity index 54% rename from net/utils/net_getrandom.c rename to libs/libc/stdlib/lib_arc4random.c index 16502c30621ae..8ff406c44c94b 100644 --- a/net/utils/net_getrandom.c +++ b/libs/libc/stdlib/lib_arc4random.c @@ -1,5 +1,5 @@ /**************************************************************************** - * net/utils/net_getrandom.c + * libs/libc/stdlib/lib_arc4random.c * * SPDX-License-Identifier: Apache-2.0 * @@ -24,9 +24,9 @@ * Included Files ****************************************************************************/ -#include - +#include #include +#include #include #include #include @@ -34,34 +34,69 @@ #include #include +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if defined(CONFIG_DEV_URANDOM) || defined(CONFIG_DEV_RANDOM) +static int getrandom_all(FAR void *buf, size_t size, int flags) +{ + FAR char *tmp = buf; + + while (size > 0) + { + ssize_t ret = getrandom(tmp, size, flags); + if (ret < 0) + { + if (get_errno() == EINTR) + { + continue; + } + + return ret; + } + + tmp += ret; + size -= ret; + } + + return 0; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: net_getrandom + * Name: arc4random_buf * * Description: - * Fill a buffer of arbitrary length with randomness. This function is - * guaranteed to be success. + * Fill a buffer of arbitrary length with randomness. This is the + * preferred interface for getting random numbers. The traditional + * /dev/random approach is susceptible for things like the attacker + * exhausting file descriptors on purpose. + * + * Note that this function cannot fail, other than by asserting. * * Input Parameters: * bytes - Buffer for returned random bytes * nbytes - Number of bytes requested. * + * Returned Value: + * None + * ****************************************************************************/ -void net_getrandom(FAR void *bytes, size_t nbytes) +void arc4random_buf(FAR void *bytes, size_t nbytes) { #if defined(CONFIG_DEV_URANDOM) || defined(CONFIG_DEV_RANDOM) - ssize_t ret = getrandom(bytes, nbytes, 0); - - if (ret < 0) + if (getrandom_all(bytes, nbytes, GRND_RANDOM) >= 0) { - ret = getrandom(bytes, nbytes, GRND_RANDOM); + return; } - if (ret == nbytes) + if (getrandom_all(bytes, nbytes, 0) >= 0) { return; } @@ -82,3 +117,27 @@ void net_getrandom(FAR void *bytes, size_t nbytes) bytes = (FAR uint8_t *)bytes + ncopy; } } + +/**************************************************************************** + * Name: arc4random + * + * Description: + * Returns a single 32-bit value. This is the preferred interface for + * getting random numbers. The traditional /dev/random approach is + * susceptible for things like the attacker exhausting file + * descriptors on purpose. + * + * Note that this function cannot fail, other than by asserting. + * + * Returned Value: + * a random 32-bit value. + * + ****************************************************************************/ + +uint32_t arc4random(void) +{ + uint32_t ret; + + arc4random_buf(&ret, sizeof(ret)); + return ret; +} diff --git a/libs/libc/unistd/lib_getentropy.c b/libs/libc/unistd/lib_getentropy.c index 078b2e3bbedbd..b4ea0598d52ed 100644 --- a/libs/libc/unistd/lib_getentropy.c +++ b/libs/libc/unistd/lib_getentropy.c @@ -24,8 +24,8 @@ * Included Files ****************************************************************************/ -#include #include +#include #include /**************************************************************************** @@ -56,30 +56,12 @@ int getentropy(FAR void *buffer, size_t length) { - FAR char *pos = buffer; - if (length > 256) { set_errno(EIO); return -1; } - while (length > 0) - { - int ret = getrandom(pos, length, 0); - if (ret < 0) - { - if (get_errno() == EINTR) - { - continue; - } - - return ret; - } - - pos += ret; - length -= ret; - } - + arc4random_buf(buffer, length); return 0; } diff --git a/libs/libc/uuid/lib_uuid_create.c b/libs/libc/uuid/lib_uuid_create.c index 40bb9757fa808..17e9be1e85748 100644 --- a/libs/libc/uuid/lib_uuid_create.c +++ b/libs/libc/uuid/lib_uuid_create.c @@ -24,39 +24,10 @@ * Included Files ****************************************************************************/ -#include #include #include #include -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static int uuid_getrandom(FAR void *buf, size_t size, int flags) -{ - FAR char *tmp = buf; - - while (size > 0) - { - ssize_t ret = getrandom(tmp, size, flags); - if (ret < 0) - { - if (get_errno() == EINTR) - { - continue; - } - - return ret; - } - - tmp += ret; - size -= ret; - } - - return 0; -} - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -74,24 +45,7 @@ static int uuid_getrandom(FAR void *buf, size_t size, int flags) void uuid_create(FAR uuid_t *u, FAR uint32_t *status) { - int ret; - - ret = uuid_getrandom(u, sizeof(uuid_t), GRND_RANDOM); - if (ret < 0) - { - ret = uuid_getrandom(u, sizeof(uuid_t), 0); - } - - if (ret < 0) - { - FAR unsigned long *beg = (FAR unsigned long *)u; - FAR unsigned long *end = (FAR unsigned long *)(u + 1); - - while (beg < end) - { - *beg++ = rand(); - } - } + arc4random_buf(u, sizeof(uuid_t)); u->clock_seq_hi_and_reserved &= ~(1 << 6); u->clock_seq_hi_and_reserved |= (1 << 7); diff --git a/net/tcp/tcp_seqno.c b/net/tcp/tcp_seqno.c index 15289af5f842e..6ab40a9f97688 100644 --- a/net/tcp/tcp_seqno.c +++ b/net/tcp/tcp_seqno.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -55,7 +56,6 @@ #include "devif/devif.h" #include "tcp/tcp.h" -#include "utils/utils.h" /**************************************************************************** * Private Data @@ -97,7 +97,7 @@ static uint32_t tcp_isn_rfc6528(FAR struct tcp_conn_s *conn) if (g_tcp_isnkey[0] == 0) { - net_getrandom(g_tcp_isnkey, sizeof(g_tcp_isnkey)); + arc4random_buf(g_tcp_isnkey, sizeof(g_tcp_isnkey)); } /* M is the 4 microsecond timer */ @@ -216,7 +216,7 @@ void tcp_initsequence(FAR struct tcp_conn_s *conn) { /* Get a random TCP sequence number */ - net_getrandom(&g_tcpsequence, sizeof(uint32_t)); + arc4random_buf(&g_tcpsequence, sizeof(uint32_t)); /* Use about half of allowed values */ diff --git a/net/utils/CMakeLists.txt b/net/utils/CMakeLists.txt index bd4534b5d09b7..8803381a3dccb 100644 --- a/net/utils/CMakeLists.txt +++ b/net/utils/CMakeLists.txt @@ -33,7 +33,6 @@ set(SRCS net_snoop.c net_cmsg.c net_iob_concat.c - net_getrandom.c net_mask2pref.c) # IPv6 utilities diff --git a/net/utils/Make.defs b/net/utils/Make.defs index 7894dd947d4fa..de2d96a28a8c5 100644 --- a/net/utils/Make.defs +++ b/net/utils/Make.defs @@ -23,8 +23,8 @@ # Common utilities NET_CSRCS += net_dsec2tick.c net_dsec2timeval.c net_timeval2dsec.c -NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c net_snoop.c -NET_CSRCS += net_cmsg.c net_iob_concat.c net_getrandom.c net_mask2pref.c +NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c +NET_CSRCS += net_snoop.c net_cmsg.c net_iob_concat.c net_mask2pref.c # IPv6 utilities diff --git a/net/utils/utils.h b/net/utils/utils.h index cfe7fcd663061..d5355d03d8d67 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -28,6 +28,9 @@ ****************************************************************************/ #include + +#include + #include #include #include @@ -41,7 +44,7 @@ #define NET_PORT_RANDOM_INIT(port) \ do \ { \ - net_getrandom(&(port), sizeof(port)); \ + arc4random_buf(&(port), sizeof(port)); \ (port) = (port) % (CONFIG_NET_DEFAULT_MAX_PORT - \ CONFIG_NET_DEFAULT_MIN_PORT + 1); \ (port) += CONFIG_NET_DEFAULT_MIN_PORT; \ @@ -187,21 +190,6 @@ unsigned int net_dsec2tick(int dsec); unsigned int net_timeval2dsec(FAR struct timeval *tv, enum tv2ds_remainder_e remainder); -/**************************************************************************** - * Name: net_getrandom - * - * Description: - * Fill a buffer of arbitrary length with randomness. This function is - * guaranteed to be success. - * - * Input Parameters: - * bytes - Buffer for returned random bytes - * nbytes - Number of bytes requested. - * - ****************************************************************************/ - -void net_getrandom(FAR void *bytes, size_t nbytes); - /**************************************************************************** * Name: net_ipv4_mask2pref * diff --git a/syscall/syscall.csv b/syscall/syscall.csv index c3e81430b2e9c..1c3baae531506 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -6,7 +6,6 @@ "aio_fsync","aio.h","defined(CONFIG_FS_AIO)","int","int","FAR struct aiocb *" "aio_read","aio.h","defined(CONFIG_FS_AIO)","int","FAR struct aiocb *" "aio_write","aio.h","defined(CONFIG_FS_AIO)","int","FAR struct aiocb *" -"arc4random_buf","stdlib.h","defined(CONFIG_CRYPTO_RANDOM_POOL)","void","FAR void *","size_t" "bind","sys/socket.h","defined(CONFIG_NET)","int","int","FAR const struct sockaddr *","socklen_t" "boardctl","sys/boardctl.h","defined(CONFIG_BOARDCTL)","int","unsigned int","uintptr_t" "chmod","sys/stat.h","","int","FAR const char *","mode_t"