From c8ea7a95a386c59ac34cb10b5d06cf14043f2415 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Thu, 24 Mar 2022 22:31:27 +0800 Subject: [PATCH] libc: Implement getrandom on top of "/dev/[u]random" https://man7.org/linux/man-pages/man2/getrandom.2.html Signed-off-by: Xiang Xiao --- include/sys/random.h | 79 +++++++++++++++++++++++++++++ libs/libc/misc/Make.defs | 2 +- libs/libc/misc/lib_getrandom.c | 91 ++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 include/sys/random.h create mode 100644 libs/libc/misc/lib_getrandom.c diff --git a/include/sys/random.h b/include/sys/random.h new file mode 100644 index 0000000000..0e472d2d3e --- /dev/null +++ b/include/sys/random.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * include/sys/random.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_SYS_RANDOM_H +#define __INCLUDE_SYS_RANDOM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Flags for getrandom(2) + * + * GRND_NONBLOCK Don't block and return EAGAIN instead + * GRND_RANDOM Open /dev/random instead of /dev/urandom + * GRND_INSECURE Return non-cryptographic random bytes + */ + +#define GRND_NONBLOCK (1 << 0) +#define GRND_RANDOM (1 << 1) +#define GRND_INSECURE (1 << 2) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: getrandom + * + * 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. + * + * Input Parameters: + * bytes - Buffer for returned random bytes + * nbytes - Number of bytes requested. + * flags - Bit mask that can contain zero or more of the ORed values + * together. + * + * Returned Value: + * On success, getrandom() returns the number of bytes that were copied + * to the buffer bytes. This may be less than the number of bytes + * requested via nbytes if either GRND_RANDOM was specified in flags and + * insufficient entropy was present in the random source or the system + * call was interrupted by a signal. + * + * On error, -1 is returned, and errno is set appropriately. + * + ****************************************************************************/ + +ssize_t getrandom(FAR void *bytes, size_t nbytes, unsigned int flags); + +#endif /* __INCLUDE_SYS_RANDOM_H */ diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index 5710b7fb42..a4c8bc8ce9 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -20,7 +20,7 @@ # Add the internal C files to the build -CSRCS += lib_mknod.c lib_umask.c lib_utsname.c +CSRCS += lib_mknod.c lib_umask.c lib_utsname.c lib_getrandom.c CSRCS += lib_xorshift128.c lib_tea_encrypt.c lib_tea_decrypt.c # Support for platforms that do not have long long types diff --git a/libs/libc/misc/lib_getrandom.c b/libs/libc/misc/lib_getrandom.c new file mode 100644 index 0000000000..42a17bdf80 --- /dev/null +++ b/libs/libc/misc/lib_getrandom.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * libs/libc/misc/lib_getrandom.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: getrandom + * + * 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. + * + * Input Parameters: + * bytes - Buffer for returned random bytes + * nbytes - Number of bytes requested. + * flags - Bit mask that can contain zero or more of the ORed values + * together. + * + * Returned Value: + * On success, getrandom() returns the number of bytes that were copied + * to the buffer bytes. This may be less than the number of bytes + * requested via nbytes if either GRND_RANDOM was specified in flags and + * insufficient entropy was present in the random source or the system + * call was interrupted by a signal. + * + * On error, -1 is returned, and errno is set appropriately. + * + ****************************************************************************/ + +ssize_t getrandom(FAR void *bytes, size_t nbytes, unsigned int flags) +{ + int oflags = O_RDONLY; + FAR const char *dev; + int fd; + + if ((flags & GRND_NONBLOCK) != 0) + { + oflags |= O_NONBLOCK; + } + + if ((flags & GRND_RANDOM) != 0) + { + dev = "/dev/random"; + } + else + { + dev = "/dev/urandom"; + } + + fd = open(dev, oflags); + if (fd < 0) + { + return fd; + } + + nbytes = read(fd, bytes, nbytes); + close(fd); + + return nbytes; +}