getentropy.c (3611ec604864a7d4dcc9a3ea898c80eb35eef8a0) getentropy.c (c1e80940f3b4030df0aaed73028053af057e476d)
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 17 unchanged lines hidden (view full) ---

26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/random.h>
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 17 unchanged lines hidden (view full) ---

26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/random.h>
34#include <sys/sysctl.h>
34
35#include <errno.h>
36#include <stdlib.h>
37
38#include "libc_private.h"
39
35
36#include <errno.h>
37#include <stdlib.h>
38
39#include "libc_private.h"
40
41extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
42
43static size_t
44arnd_sysctl(u_char *buf, size_t size)
45{
46 int mib[2];
47 size_t len, done;
48
49 mib[0] = CTL_KERN;
50 mib[1] = KERN_ARND;
51 done = 0;
52
53 do {
54 len = size;
55 if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
56 return (done);
57 done += len;
58 buf += len;
59 size -= len;
60 } while (size > 0);
61
62 return (done);
63}
64
40/*
41 * If a newer libc is accidentally installed on an older kernel, provide high
42 * quality random data anyway. The sysctl interface is not as fast and does
43 * not block by itself, but is provided by even very old kernels.
44 */
45static int
46getentropy_fallback(void *buf, size_t buflen)
47{
48 /*
49 * oldp (buf) == NULL has a special meaning for sysctl that results in
50 * no EFAULT. For compatibility with the kernel getrandom(2), detect
51 * this case and return the appropriate error.
52 */
53 if (buf == NULL && buflen > 0) {
54 errno = EFAULT;
55 return (-1);
56 }
65/*
66 * If a newer libc is accidentally installed on an older kernel, provide high
67 * quality random data anyway. The sysctl interface is not as fast and does
68 * not block by itself, but is provided by even very old kernels.
69 */
70static int
71getentropy_fallback(void *buf, size_t buflen)
72{
73 /*
74 * oldp (buf) == NULL has a special meaning for sysctl that results in
75 * no EFAULT. For compatibility with the kernel getrandom(2), detect
76 * this case and return the appropriate error.
77 */
78 if (buf == NULL && buflen > 0) {
79 errno = EFAULT;
80 return (-1);
81 }
57 if (__arc4_sysctl(buf, buflen) != buflen) {
82 if (arnd_sysctl(buf, buflen) != buflen) {
58 if (errno == EFAULT)
59 return (-1);
60 /*
61 * This cannot happen. _arc4_sysctl() spins until the random
62 * device is seeded and then repeatedly reads until the full
63 * request is satisfied. The only way for this to return a zero
64 * byte or short read is if sysctl(2) on the kern.arandom MIB
65 * fails. In this case, exceping the user-provided-a-bogus-

--- 38 unchanged lines hidden ---
83 if (errno == EFAULT)
84 return (-1);
85 /*
86 * This cannot happen. _arc4_sysctl() spins until the random
87 * device is seeded and then repeatedly reads until the full
88 * request is satisfied. The only way for this to return a zero
89 * byte or short read is if sysctl(2) on the kern.arandom MIB
90 * fails. In this case, exceping the user-provided-a-bogus-

--- 38 unchanged lines hidden ---