posix: Introduce getentropy() function

The function writes random data to the provided buffer. Maximum
permitted buffer size is 256 bytes. On success the function returns 0,
otherwise it returns -1 and sets errno to appropriate value.

Signed-off-by: Patryk Duda <patrykd@google.com>
This commit is contained in:
Patryk Duda 2024-04-12 13:34:46 +02:00 committed by Fabio Baltieri
parent 1542140e4e
commit ef258166ba
9 changed files with 153 additions and 0 deletions

View file

@ -263,6 +263,7 @@ extern char *optarg;
extern int opterr, optind, optopt;
#endif
int getentropy(void *buffer, size_t length);
pid_t getpid(void);
unsigned sleep(unsigned int seconds);
int usleep(useconds_t useconds);

View file

@ -36,6 +36,7 @@ zephyr_library()
add_subdirectory_ifdef(CONFIG_GETOPT getopt)
zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c)
zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c)
zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c)
zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK clock.c)

View file

@ -35,6 +35,7 @@ rsource "Kconfig.eventfd"
rsource "Kconfig.fdtable"
rsource "Kconfig.fnmatch"
rsource "Kconfig.fs"
rsource "Kconfig.getentropy"
rsource "Kconfig.getopt"
rsource "Kconfig.key"
rsource "Kconfig.mqueue"

View file

@ -0,0 +1,14 @@
# Copyright (c) 2024 Google LLC
#
# SPDX-License-Identifier: Apache-2.0
DT_CHOSEN_ZEPHYR_ENTROPY := zephyr,entropy
config GETENTROPY
bool "Support for getentropy"
depends on !NATIVE_APPLICATION
select NATIVE_LIBC_INCOMPATIBLE
depends on ENTROPY_HAS_DRIVER
depends on $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_ENTROPY))
help
Enable support for getentropy() function.

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <zephyr/drivers/entropy.h>
#include <zephyr/kernel.h>
#include <zephyr/posix/unistd.h>
#define ENTROPY_NODE DT_CHOSEN(zephyr_entropy)
int getentropy(void *buffer, size_t length)
{
const struct device * const entropy = DEVICE_DT_GET(ENTROPY_NODE);
if (!buffer) {
errno = EFAULT;
return -1;
}
if (length > 256) {
errno = EIO;
return -1;
}
if (!device_is_ready(entropy)) {
errno = EIO;
return -1;
}
/*
* getentropy() uses size_t to represent buffer size, but Zephyr uses
* uint16_t. The length check above allows us to safely cast without
* overflow.
*/
if (entropy_get_entropy(entropy, buffer, (uint16_t)length)) {
errno = EIO;
return -1;
}
return 0;
}

View file

@ -0,0 +1,10 @@
# Copyright (c) 2024 Google LLC
#
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(getentropy)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,4 @@
CONFIG_ENTROPY_GENERATOR=y
CONFIG_GETENTROPY=y
CONFIG_POSIX_API=y
CONFIG_ZTEST=y

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <unistd.h>
ZTEST(getentropy_test_suite, test_getentropy_too_large)
{
uint8_t buf[256 + 1] = { 0 };
int ret;
ret = getentropy(buf, sizeof(buf));
zassert_equal(ret, -1);
zassert_equal(errno, EIO);
}
ZTEST(getentropy_test_suite, test_getentropy_null_buffer)
{
int ret;
ret = getentropy(NULL, 0);
zassert_equal(ret, -1);
zassert_equal(errno, EFAULT);
}
ZTEST(getentropy_test_suite, test_getentropy_max_size)
{
uint8_t buf[256] = { 0 };
int ret;
ret = getentropy(buf, sizeof(buf));
zassert_equal(ret, 0);
}
ZTEST(getentropy_test_suite, test_getentropy)
{
uint8_t zero[16] = { 0 };
uint8_t buf1[16];
uint8_t buf2[16];
int ret;
ret = getentropy(buf1, sizeof(buf1));
zassert_equal(ret, 0);
ret = getentropy(buf2, sizeof(buf2));
zassert_equal(ret, 0);
zassert_true(memcmp(buf1, zero, sizeof(zero)) != 0);
zassert_true(memcmp(buf2, zero, sizeof(zero)) != 0);
zassert_true(memcmp(buf1, buf2, sizeof(buf1)) != 0);
}
ZTEST_SUITE(getentropy_test_suite, NULL, NULL, NULL, NULL, NULL);

View file

@ -0,0 +1,20 @@
common:
filter: dt_chosen_enabled("zephyr,entropy") and CONFIG_ENTROPY_HAS_DRIVER and
not CONFIG_NATIVE_LIBC
integration_platforms:
- native_sim
tags:
- posix
- getentropy
tests:
portability.posix.getentropy: {}
portability.posix.getentropy.newlib:
filter: CONFIG_NEWLIB_LIBC_SUPPORTED
extra_configs:
- CONFIG_NEWLIB_LIBC=y
- CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=4096
portability.posix.getentropy.picolibc:
tags: picolibc
filter: CONFIG_PICOLIBC_SUPPORTED
extra_configs:
- CONFIG_PICOLIBC=y