]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-random-util.c
test: drop log_trace() in test-random-util
[thirdparty/systemd.git] / src / test / test-random-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2416f73b 2
f2a8b8de
ZJS
3#include <math.h>
4
2416f73b 5#include "hexdecoct.h"
2416f73b 6#include "log.h"
f2a8b8de
ZJS
7#include "memory-util.h"
8#include "random-util.h"
9#include "terminal-util.h"
6d7c4033 10#include "tests.h"
2416f73b 11
94d457e8 12static void test_genuine_random_bytes(RandomFlags flags) {
2416f73b 13 uint8_t buf[16] = {};
2416f73b
ZJS
14
15 log_info("/* %s */", __func__);
16
93457c0c 17 for (size_t i = 1; i < sizeof buf; i++) {
94d457e8 18 assert_se(genuine_random_bytes(buf, i, flags) == 0);
2416f73b
ZJS
19 if (i + 1 < sizeof buf)
20 assert_se(buf[i] == 0);
21
22 hexdump(stdout, buf, i);
23 }
24}
25
3335dc2d 26static void test_pseudo_random_bytes(void) {
2416f73b 27 uint8_t buf[16] = {};
2416f73b
ZJS
28
29 log_info("/* %s */", __func__);
30
93457c0c 31 for (size_t i = 1; i < sizeof buf; i++) {
3335dc2d 32 pseudo_random_bytes(buf, i);
2416f73b
ZJS
33 if (i + 1 < sizeof buf)
34 assert_se(buf[i] == 0);
35
36 hexdump(stdout, buf, i);
37 }
38}
39
33dbab6f 40static void test_rdrand(void) {
93457c0c 41 int r;
97fa202a 42
93457c0c
ZJS
43 log_info("/* %s */", __func__);
44
45 for (unsigned i = 0; i < 10; i++) {
33dbab6f 46 unsigned long x = 0;
97fa202a 47
33dbab6f 48 r = rdrand(&x);
97fa202a
LP
49 if (r < 0) {
50 log_error_errno(r, "RDRAND failed: %m");
51 return;
52 }
53
33dbab6f 54 printf("%lx\n", x);
97fa202a
LP
55 }
56}
57
f2a8b8de
ZJS
58#define TOTAL 100000
59
60static void test_random_u64_range_one(unsigned mod) {
61 log_info("/* %s(%u) */", __func__, mod);
62
63 unsigned max = 0, count[mod];
64 zero(count);
65
66 for (unsigned i = 0; i < TOTAL; i++) {
67 uint64_t x;
68
69 x = random_u64_range(mod);
70
f2a8b8de
ZJS
71 count[x]++;
72 max = MAX(max, count[x]);
73 }
74
75 /* Print histogram: vertical axis — value, horizontal axis — count.
76 *
77 * The expected value is always TOTAL/mod, because the distribution should be flat. The expected
78 * variance is TOTAL×p×(1-p), where p==1/mod, and standard deviation the root of the variance.
79 * Assert that the deviation from the expected value is less than 6 standard deviations.
80 */
81 unsigned scale = 2 * max / (columns() < 20 ? 80 : columns() - 20);
82 double exp = (double) TOTAL / mod;
83
84 for (size_t i = 0; i < mod; i++) {
85 double dev = (count[i] - exp) / sqrt(exp * (mod > 1 ? mod - 1 : 1) / mod);
86 log_debug("%02zu: %5u (%+.3f)%*s",
87 i, count[i], dev,
88 count[i] / scale, "x");
89
90 assert_se(fabs(dev) < 6); /* 6 sigma is excessive, but this check should be enough to
91 * identify catastrophic failure while minimizing false
92 * positives. */
93 }
94}
95
96static void test_random_u64_range(void) {
97 for (unsigned mod = 1; mod < 29; mod++)
98 test_random_u64_range_one(mod);
99}
100
2416f73b 101int main(int argc, char **argv) {
6d7c4033 102 test_setup_logging(LOG_DEBUG);
2416f73b 103
94d457e8
LP
104 test_genuine_random_bytes(RANDOM_EXTEND_WITH_PSEUDO);
105 test_genuine_random_bytes(0);
68534345 106 test_genuine_random_bytes(RANDOM_BLOCK);
cc83d519 107 test_genuine_random_bytes(RANDOM_ALLOW_RDRAND);
0497c4c2 108 test_genuine_random_bytes(RANDOM_ALLOW_INSECURE);
2416f73b 109
3335dc2d 110 test_pseudo_random_bytes();
33dbab6f 111 test_rdrand();
f2a8b8de 112 test_random_u64_range();
97fa202a 113
2416f73b
ZJS
114 return 0;
115}