Linux: Assume and consolidate socket wire-up syscall
[glibc.git] / stdlib / tst-arc4random-stats.c
blobf6fc1f10c40d18f951a7f532af55a1170effbfe6
1 /* Statistical tests for arc4random-related functions.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <array_length.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <support/check.h>
27 enum
29 arc4random_key_size = 32
32 struct key
34 unsigned char data[arc4random_key_size];
37 /* With 12,000 keys, the probability that a byte in a predetermined
38 position does not have a predetermined value in all generated keys
39 is about 4e-21. The probability that this happens with any of the
40 16 * 256 possible byte position/values is 1.6e-17. This results in
41 an acceptably low false-positive rate. */
42 enum { key_count = 12000 };
44 static struct key keys[key_count];
46 /* Used to perform the distribution check. */
47 static int byte_counts[arc4random_key_size][256];
49 /* Bail out after this many failures. */
50 enum { failure_limit = 100 };
52 static void
53 find_stuck_bytes (bool (*func) (unsigned char *key))
55 memset (&keys, 0xcc, sizeof (keys));
57 int failures = 0;
58 for (int key = 0; key < key_count; ++key)
60 while (true)
62 if (func (keys[key].data))
63 break;
64 ++failures;
65 if (failures >= failure_limit)
67 printf ("warning: bailing out after %d failures\n", failures);
68 return;
72 printf ("info: key generation finished with %d failures\n", failures);
74 memset (&byte_counts, 0, sizeof (byte_counts));
75 for (int key = 0; key < key_count; ++key)
76 for (int pos = 0; pos < arc4random_key_size; ++pos)
77 ++byte_counts[pos][keys[key].data[pos]];
79 for (int pos = 0; pos < arc4random_key_size; ++pos)
80 for (int byte = 0; byte < 256; ++byte)
81 if (byte_counts[pos][byte] == 0)
83 support_record_failure ();
84 printf ("error: byte %d never appeared at position %d\n", byte, pos);
88 /* Test adapter for arc4random. */
89 static bool
90 generate_arc4random (unsigned char *key)
92 uint32_t words[arc4random_key_size / 4];
93 _Static_assert (sizeof (words) == arc4random_key_size, "sizeof (words)");
95 for (int i = 0; i < array_length (words); ++i)
96 words[i] = arc4random ();
97 memcpy (key, &words, arc4random_key_size);
98 return true;
101 /* Test adapter for arc4random_buf. */
102 static bool
103 generate_arc4random_buf (unsigned char *key)
105 arc4random_buf (key, arc4random_key_size);
106 return true;
109 /* Test adapter for arc4random_uniform. */
110 static bool
111 generate_arc4random_uniform (unsigned char *key)
113 for (int i = 0; i < arc4random_key_size; ++i)
114 key[i] = arc4random_uniform (256);
115 return true;
118 /* Test adapter for arc4random_uniform with argument 257. This means
119 that byte 0 happens more often, but we do not perform such a
120 statistcal check, so the test will still pass */
121 static bool
122 generate_arc4random_uniform_257 (unsigned char *key)
124 for (int i = 0; i < arc4random_key_size; ++i)
125 key[i] = arc4random_uniform (257);
126 return true;
129 static int
130 do_test (void)
132 puts ("info: arc4random implementation test");
133 find_stuck_bytes (generate_arc4random);
135 puts ("info: arc4random_buf implementation test");
136 find_stuck_bytes (generate_arc4random_buf);
138 puts ("info: arc4random_uniform implementation test");
139 find_stuck_bytes (generate_arc4random_uniform);
141 puts ("info: arc4random_uniform implementation test (257 variant)");
142 find_stuck_bytes (generate_arc4random_uniform_257);
144 return 0;
147 #include <support/test-driver.c>