diff options
| author | Mattias Andrée <m@maandree.se> | 2026-05-11 23:15:33 +0200 |
|---|---|---|
| committer | Mattias Andrée <m@maandree.se> | 2026-05-11 23:15:33 +0200 |
| commit | 86087e5f9cf4a0512ba36b4d01086b905574a47d (patch) | |
| tree | 03ce90743ef4d9e3da6ba45b70f11494e12b667c /libtest/random.c | |
| parent | Misc (diff) | |
| download | librecrypt-86087e5f9cf4a0512ba36b4d01086b905574a47d.tar.gz librecrypt-86087e5f9cf4a0512ba36b4d01086b905574a47d.tar.bz2 librecrypt-86087e5f9cf4a0512ba36b4d01086b905574a47d.tar.xz | |
Misc
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
| -rw-r--r-- | libtest/random.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/libtest/random.c b/libtest/random.c new file mode 100644 index 0000000..77e9218 --- /dev/null +++ b/libtest/random.c @@ -0,0 +1,140 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#ifndef TEST + + +unsigned char *libtest_random_pattern = NULL; +size_t libtest_random_pattern_length = 0u; +size_t libtest_random_pattern_offset = 0u; + +static ssize_t +genpattern(void *buf, size_t size) +{ + unsigned char *out = buf; + size_t n; + + if (size > (size_t)SSIZE_MAX) + size = (size_t)SSIZE_MAX; + + if (libtest_random_pattern_length) { + while (size) { + if (libtest_random_pattern_offset == libtest_random_pattern_length) + libtest_random_pattern_offset = 0u; + n = libtest_random_pattern_length - libtest_random_pattern_offset; + if (n > size) + n = size; + memcpy(out, &libtest_random_pattern[libtest_random_pattern_offset], n); + out = &out[n]; + size -= n; + libtest_random_pattern_offset += n; + } + } else { + for (; size; size--, out++) + out[0] = (unsigned char)rand(); + } + + return (ssize_t)size; +} + + +#if defined(__linux__) +int libtest_getrandom_real = 1; +int libtest_getrandom_error = 0; +size_t libtest_getrandom_max_return = SIZE_MAX; + +ssize_t +(getrandom)(void *buf, size_t size, unsigned int flags) +{ + if (size > libtest_getrandom_max_return) + size = libtest_getrandom_max_return; + + if (libtest_getrandom_error) { + errno = libtest_getrandom_error; + if (libtest_getrandom_error == EINTR) + libtest_getrandom_error = 0; + return -1; + } + + if (!libtest_getrandom_real) + return genpattern(buf, size); + +# if defined(SYS_getrandom) + return syscall(SYS_getrandom, buf, size, flags); +# else + errno = ENOSYS; + return -1; +# endif +} +#endif + + +int libtest_getentropy_real = 1; +int libtest_getentropy_error = 0; +size_t libtest_getentropy_calls = 0u; +int libtest_getentropy_jmp_val = 0; +jmp_buf libtest_getentropy_jmp; + +int +(getentropy)(void *buf, size_t size) +{ + unsigned char *out = buf; + ssize_t r; + + libtest_getentropy_calls += 1u; + + if (libtest_getentropy_jmp_val) + longjmp(libtest_getentropy_jmp, libtest_getentropy_jmp_val); + + if (libtest_getentropy_error) { + errno = libtest_getentropy_error; + if (libtest_getentropy_error == EINTR) + libtest_getentropy_error = 0; + return -1; + } + + if (size > 256u) { + errno = EIO; + return -1; + } + + if (!libtest_getentropy_real) { + r = genpattern(out, size); + if (r == (ssize_t)size) + return 0; + errno = EIO; + return -1; + } + +#if defined(__linux__) && defined(SYS_getrandom) + while (size) { + r = (ssize_t)syscall(SYS_getrandom, out, size, 0); + if (r < 0) { + if (errno == EINTR) + continue; + if (errno != ENOSYS) + errno = EIO; + return -1; + } + out = &out[r]; + size -= (size_t)r; + } + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} + + +#else + + +CONST int +main(void) +{ + /* TODO maybe test */ + return 0; +} + + +#endif |
