1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_general.h"
18 #include "apr_pools.h"
19 #include "apr_random.h"
20 #include "apr_thread_proc.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include "testutil.h"
24
25 #define RANDOM_BUF_SZ 128
26
hexdump(const char * msg,const unsigned char * b,int n)27 static void hexdump(const char *msg, const unsigned char *b, int n)
28 {
29 int i;
30
31 printf("\n%s", msg);
32 for (i = 0; i < n; ++i) {
33 #if 0
34 if ((i & 0xf) == 0)
35 printf("%04x", i);
36 printf(" %02x", b[i]);
37 if ((i & 0xf) == 0xf)
38 printf("\n");
39 #else
40 printf("0x%02x,", b[i]);
41 if ((i & 7) == 7)
42 printf("\n");
43 #endif
44 }
45 printf("\n");
46 }
47
48 static apr_random_t *r;
49
50 typedef apr_status_t APR_THREAD_FUNC rnd_fn(apr_random_t * r, void *b,
51 apr_size_t n);
52
rand_run_kat(abts_case * tc,rnd_fn * f,apr_random_t * r,const unsigned char expected[RANDOM_BUF_SZ])53 static void rand_run_kat(abts_case *tc, rnd_fn *f, apr_random_t *r,
54 const unsigned char expected[RANDOM_BUF_SZ])
55 {
56 unsigned char c[RANDOM_BUF_SZ];
57 apr_status_t rv;
58
59 rv = f(r, c, RANDOM_BUF_SZ);
60 ABTS_INT_EQUAL(tc, 0, rv);
61 if (rv)
62 return;
63 if (memcmp(c, expected, RANDOM_BUF_SZ)) {
64 hexdump("Generated: ", c, RANDOM_BUF_SZ);
65 hexdump("Expected: ", expected, RANDOM_BUF_SZ);
66 ABTS_FAIL(tc, "Randomness mismatch");
67 }
68 }
69
70 #if APR_HAS_FORK
rand_check_kat(rnd_fn * f,apr_random_t * r,const unsigned char expected[RANDOM_BUF_SZ],apr_file_t * readp,apr_file_t * writep)71 static int rand_check_kat(rnd_fn *f, apr_random_t *r,
72 const unsigned char expected[RANDOM_BUF_SZ],
73 apr_file_t *readp, apr_file_t *writep)
74 {
75 apr_size_t nbytes = RANDOM_BUF_SZ;
76 apr_size_t cmd_size = 1;
77 unsigned char c[RANDOM_BUF_SZ];
78 char ack;
79 apr_status_t rv;
80
81 rv = f(r, c, RANDOM_BUF_SZ);
82 if (rv)
83 return 2;
84 rv = 0;
85 if (memcmp(c, expected, RANDOM_BUF_SZ)) {
86 rv = 1;
87 } else {
88 hexdump("Generated: ", c, RANDOM_BUF_SZ);
89 hexdump("Previous: ", expected, RANDOM_BUF_SZ);
90 }
91 /* Report back our random values for comparison in another child */
92 apr_file_write(writep, c, &nbytes);
93 /* Wait for our parent ack the data */
94 apr_file_read(readp, &ack, &cmd_size);
95 return rv;
96 }
97 #endif
98
rand_add_zeroes(apr_random_t * r)99 static void rand_add_zeroes(apr_random_t *r)
100 {
101 static unsigned char c[2048];
102
103 apr_random_add_entropy(r, c, sizeof c);
104 }
105
rand_run_seed_short(abts_case * tc,rnd_fn * f,apr_random_t * r,int count)106 static void rand_run_seed_short(abts_case *tc, rnd_fn *f, apr_random_t *r,
107 int count)
108 {
109 int i;
110 apr_status_t rv;
111 char c[1];
112
113 for (i = 0; i < count; ++i)
114 rand_add_zeroes(r);
115 rv = f(r, c, 1);
116 ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTENOUGHENTROPY(rv));
117 }
118
rand_seed_short(abts_case * tc,void * data)119 static void rand_seed_short(abts_case *tc, void *data)
120 {
121 r = apr_random_standard_new(p);
122 rand_run_seed_short(tc, apr_random_insecure_bytes, r, 32);
123 }
124
rand_kat(abts_case * tc,void * data)125 static void rand_kat(abts_case *tc, void *data)
126 {
127 unsigned char expected[RANDOM_BUF_SZ] = {
128 0x82, 0x04, 0xad, 0xd2, 0x0b, 0xd5, 0xac, 0xda,
129 0x3d, 0x85, 0x58, 0x38, 0x54, 0x6b, 0x69, 0x45,
130 0x37, 0x4c, 0xc7, 0xd7, 0x87, 0xeb, 0xbf, 0xd9,
131 0xb1, 0xb8, 0xb8, 0x2d, 0x9b, 0x33, 0x6e, 0x97,
132 0x04, 0x1d, 0x4c, 0xb0, 0xd1, 0xdf, 0x3d, 0xac,
133 0xd2, 0xaa, 0xfa, 0xcd, 0x96, 0xb7, 0xcf, 0xb1,
134 0x8e, 0x3d, 0xb3, 0xe5, 0x37, 0xa9, 0x95, 0xb4,
135 0xaa, 0x3d, 0x11, 0x1a, 0x08, 0x20, 0x21, 0x9f,
136 0xdb, 0x08, 0x3a, 0xb9, 0x57, 0x9f, 0xf2, 0x1f,
137 0x27, 0xdc, 0xb6, 0xc0, 0x85, 0x08, 0x05, 0xbb,
138 0x13, 0xbe, 0xb1, 0xe9, 0x63, 0x2a, 0xe2, 0xa4,
139 0x23, 0x15, 0x2a, 0x10, 0xbf, 0xdf, 0x09, 0xb3,
140 0xc7, 0xfb, 0x2d, 0x87, 0x48, 0x19, 0xfb, 0xc0,
141 0x15, 0x8c, 0xcb, 0xc6, 0xbd, 0x89, 0x38, 0x69,
142 0xa3, 0xae, 0xa3, 0x21, 0x58, 0x50, 0xe7, 0xc4,
143 0x87, 0xec, 0x2e, 0xb1, 0x2d, 0x6a, 0xbd, 0x46
144 };
145
146 rand_add_zeroes(r);
147 rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
148 }
149
rand_seed_short2(abts_case * tc,void * data)150 static void rand_seed_short2(abts_case *tc, void *data)
151 {
152 rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
153 }
154
rand_kat2(abts_case * tc,void * data)155 static void rand_kat2(abts_case *tc, void *data)
156 {
157 unsigned char expected[RANDOM_BUF_SZ] = {
158 0x38, 0x8f, 0x01, 0x29, 0x5a, 0x5c, 0x1f, 0xa8,
159 0x00, 0xde, 0x16, 0x4c, 0xe5, 0xf7, 0x1f, 0x58,
160 0xc0, 0x67, 0xe2, 0x98, 0x3d, 0xde, 0x4a, 0x75,
161 0x61, 0x3f, 0x23, 0xd8, 0x45, 0x7a, 0x10, 0x60,
162 0x59, 0x9b, 0xd6, 0xaf, 0xcb, 0x0a, 0x2e, 0x34,
163 0x9c, 0x39, 0x5b, 0xd0, 0xbc, 0x9a, 0xf0, 0x7b,
164 0x7f, 0x40, 0x8b, 0x33, 0xc0, 0x0e, 0x2a, 0x56,
165 0xfc, 0xe5, 0xab, 0xde, 0x7b, 0x13, 0xf5, 0xec,
166 0x15, 0x68, 0xb8, 0x09, 0xbc, 0x2c, 0x15, 0xf0,
167 0x7b, 0xef, 0x2a, 0x97, 0x19, 0xa8, 0x69, 0x51,
168 0xdf, 0xb0, 0x5f, 0x1a, 0x4e, 0xdf, 0x42, 0x02,
169 0x71, 0x36, 0xa7, 0x25, 0x64, 0x85, 0xe2, 0x72,
170 0xc7, 0x87, 0x4d, 0x7d, 0x15, 0xbb, 0x15, 0xd1,
171 0xb1, 0x62, 0x0b, 0x25, 0xd9, 0xd3, 0xd9, 0x5a,
172 0xe3, 0x47, 0x1e, 0xae, 0x67, 0xb4, 0x19, 0x9e,
173 0xed, 0xd2, 0xde, 0xce, 0x18, 0x70, 0x57, 0x12
174 };
175
176 rand_add_zeroes(r);
177 rand_run_kat(tc, apr_random_secure_bytes, r, expected);
178 }
179
rand_barrier(abts_case * tc,void * data)180 static void rand_barrier(abts_case *tc, void *data)
181 {
182 apr_random_barrier(r);
183 rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
184 }
185
rand_kat3(abts_case * tc,void * data)186 static void rand_kat3(abts_case *tc, void *data)
187 {
188 unsigned char expected[RANDOM_BUF_SZ] = {
189 0xe8, 0xe7, 0xc9, 0x45, 0xe2, 0x2a, 0x54, 0xb2,
190 0xdd, 0xe0, 0xf9, 0xbc, 0x3d, 0xf9, 0xce, 0x3c,
191 0x4c, 0xbd, 0xc9, 0xe2, 0x20, 0x4a, 0x35, 0x1c,
192 0x04, 0x52, 0x7f, 0xb8, 0x0f, 0x60, 0x89, 0x63,
193 0x8a, 0xbe, 0x0a, 0x44, 0xac, 0x5d, 0xd8, 0xeb,
194 0x24, 0x7d, 0xd1, 0xda, 0x4d, 0x86, 0x9b, 0x94,
195 0x26, 0x56, 0x4a, 0x5e, 0x30, 0xea, 0xd4, 0xa9,
196 0x9a, 0xdf, 0xdd, 0xb6, 0xb1, 0x15, 0xe0, 0xfa,
197 0x28, 0xa4, 0xd6, 0x95, 0xa4, 0xf1, 0xd8, 0x6e,
198 0xeb, 0x8c, 0xa4, 0xac, 0x34, 0xfe, 0x06, 0x92,
199 0xc5, 0x09, 0x99, 0x86, 0xdc, 0x5a, 0x3c, 0x92,
200 0xc8, 0x3e, 0x52, 0x00, 0x4d, 0x01, 0x43, 0x6f,
201 0x69, 0xcf, 0xe2, 0x60, 0x9c, 0x23, 0xb3, 0xa5,
202 0x5f, 0x51, 0x47, 0x8c, 0x07, 0xde, 0x60, 0xc6,
203 0x04, 0xbf, 0x32, 0xd6, 0xdc, 0xb7, 0x31, 0x01,
204 0x29, 0x51, 0x51, 0xb3, 0x19, 0x6e, 0xe4, 0xf8
205 };
206
207 rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
208 }
209
rand_kat4(abts_case * tc,void * data)210 static void rand_kat4(abts_case *tc, void *data)
211 {
212 unsigned char expected[RANDOM_BUF_SZ] = {
213 0x7d, 0x0e, 0xc4, 0x4e, 0x3e, 0xac, 0x86, 0x50,
214 0x37, 0x95, 0x7a, 0x98, 0x23, 0x26, 0xa7, 0xbf,
215 0x60, 0xfb, 0xa3, 0x70, 0x90, 0xc3, 0x58, 0xc6,
216 0xbd, 0xd9, 0x5e, 0xa6, 0x77, 0x62, 0x7a, 0x5c,
217 0x96, 0x83, 0x7f, 0x80, 0x3d, 0xf4, 0x9c, 0xcc,
218 0x9b, 0x0c, 0x8c, 0xe1, 0x72, 0xa8, 0xfb, 0xc9,
219 0xc5, 0x43, 0x91, 0xdc, 0x9d, 0x92, 0xc2, 0xce,
220 0x1c, 0x5e, 0x36, 0xc7, 0x87, 0xb1, 0xb4, 0xa3,
221 0xc8, 0x69, 0x76, 0xfc, 0x35, 0x75, 0xcb, 0x08,
222 0x2f, 0xe3, 0x98, 0x76, 0x37, 0x80, 0x04, 0x5c,
223 0xb8, 0xb0, 0x7f, 0xb2, 0xda, 0xe3, 0xa3, 0xba,
224 0xed, 0xff, 0xf5, 0x9d, 0x3b, 0x7b, 0xf3, 0x32,
225 0x6c, 0x50, 0xa5, 0x3e, 0xcc, 0xe1, 0x84, 0x9c,
226 0x17, 0x9e, 0x80, 0x64, 0x09, 0xbb, 0x62, 0xf1,
227 0x95, 0xf5, 0x2c, 0xc6, 0x9f, 0x6a, 0xee, 0x6d,
228 0x17, 0x35, 0x5f, 0x35, 0x8d, 0x55, 0x0c, 0x07
229 };
230
231 rand_add_zeroes(r);
232 rand_run_kat(tc, apr_random_secure_bytes, r, expected);
233 }
234
235 #if APR_HAS_FORK
rand_fork(abts_case * tc,void * data)236 static void rand_fork(abts_case *tc, void *data)
237 {
238 apr_proc_t proc;
239 apr_status_t rv;
240 apr_size_t nbytes = RANDOM_BUF_SZ;
241 apr_size_t cmd_size = 1;
242 char cmd = 'X';
243 unsigned char expected[RANDOM_BUF_SZ] = {
244 0xac, 0x93, 0xd2, 0x5c, 0xc7, 0xf5, 0x8d, 0xc2,
245 0xd8, 0x8d, 0xb6, 0x7a, 0x94, 0xe1, 0x83, 0x4c,
246 0x26, 0xe2, 0x38, 0x6d, 0xf5, 0xbd, 0x9d, 0x6e,
247 0x91, 0x77, 0x3a, 0x4b, 0x9b, 0xef, 0x9b, 0xa3,
248 0x9f, 0xf6, 0x6d, 0x0c, 0xdc, 0x4b, 0x02, 0xe9,
249 0x5d, 0x3d, 0xfc, 0x92, 0x6b, 0xdf, 0xc9, 0xef,
250 0xb9, 0xa8, 0x74, 0x09, 0xa3, 0xff, 0x64, 0x8d,
251 0x19, 0xc1, 0x31, 0x31, 0x17, 0xe1, 0xb7, 0x7a,
252 0xe7, 0x55, 0x14, 0x92, 0x05, 0xe3, 0x1e, 0xb8,
253 0x9b, 0x1b, 0xdc, 0xac, 0x0e, 0x15, 0x08, 0xa2,
254 0x93, 0x13, 0xf6, 0x04, 0xc6, 0x9d, 0xf8, 0x7f,
255 0x26, 0x32, 0x68, 0x43, 0x2e, 0x5a, 0x4f, 0x47,
256 0xe8, 0xf8, 0x59, 0xb7, 0xfb, 0xbe, 0x30, 0x04,
257 0xb6, 0x63, 0x6f, 0x19, 0xf3, 0x2c, 0xd4, 0xeb,
258 0x32, 0x8a, 0x54, 0x01, 0xd0, 0xaf, 0x3f, 0x13,
259 0xc1, 0x7f, 0x10, 0x2e, 0x08, 0x1c, 0x28, 0x4b,
260 };
261
262 apr_file_t *readdatap = NULL;
263 apr_file_t *writedatap = NULL;
264 apr_file_t *readcmdp = NULL;
265 apr_file_t *writecmdp = NULL;
266 apr_pool_t *p;
267 int i;
268
269 apr_pool_create(&p, NULL);
270 /* Set up data pipe for children */
271 rv = apr_file_pipe_create(&readdatap, &writedatap, p);
272 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
273 ABTS_PTR_NOTNULL(tc, readdatap);
274 ABTS_PTR_NOTNULL(tc, writedatap);
275 /* Set up cmd pipe for children */
276 rv = apr_file_pipe_create(&readcmdp, &writecmdp, p);
277 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
278 ABTS_PTR_NOTNULL(tc, readcmdp);
279 ABTS_PTR_NOTNULL(tc, writecmdp);
280
281 rand_run_kat(tc, apr_random_secure_bytes, r, expected);
282
283 for (i = 0; i< 10; i++)
284 {
285 rv = apr_proc_fork(&proc, p);
286 if (rv == APR_INCHILD) {
287 int n = rand_check_kat(apr_random_secure_bytes, r, expected, readcmdp, writedatap);
288 exit(n);
289 }
290 else if (rv == APR_INPARENT) {
291 int exitcode;
292 apr_exit_why_e why;
293
294 /* Read the random data generated by child */
295 rv = apr_file_read(readdatap, expected, &nbytes);
296 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
297 /* Tell child to finish */
298 rv = apr_file_write(writecmdp, &cmd, &cmd_size);
299 ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
300 apr_proc_wait(&proc, &exitcode, &why, APR_WAIT);
301 if (why != APR_PROC_EXIT) {
302 ABTS_FAIL(tc, "Child terminated abnormally");
303 }
304 else if (exitcode == 0) {
305 if (i == 0)
306 {
307 ABTS_FAIL(tc, "Child produced our randomness");
308 } else
309 {
310 ABTS_FAIL(tc, "Child produced randomness of previous child");
311 }
312 }
313 else if (exitcode == 2) {
314 ABTS_FAIL(tc, "Child randomness failed");
315 }
316 else if (exitcode != 1) {
317 ABTS_FAIL(tc, "Unknown child error");
318 }
319 } else {
320 ABTS_FAIL(tc, "Fork failed");
321 }
322 }
323
324 }
325 #endif
326
rand_exists(abts_case * tc,void * data)327 static void rand_exists(abts_case *tc, void *data)
328 {
329 #if !APR_HAS_RANDOM
330 ABTS_NOT_IMPL(tc, "apr_generate_random_bytes");
331 #else
332 unsigned char c[42];
333
334 /* There must be a better way to test random-ness, but I don't know
335 * what it is right now.
336 */
337 APR_ASSERT_SUCCESS(tc, "apr_generate_random_bytes failed",
338 apr_generate_random_bytes(c, sizeof c));
339 #endif
340 }
341
testrand(abts_suite * suite)342 abts_suite *testrand(abts_suite *suite)
343 {
344 suite = ADD_SUITE(suite)
345
346 abts_run_test(suite, rand_exists, NULL);
347 abts_run_test(suite, rand_seed_short, NULL);
348 abts_run_test(suite, rand_kat, NULL);
349 abts_run_test(suite, rand_seed_short2, NULL);
350 abts_run_test(suite, rand_kat2, NULL);
351 abts_run_test(suite, rand_barrier, NULL);
352 abts_run_test(suite, rand_kat3, NULL);
353 abts_run_test(suite, rand_kat4, NULL);
354 #if APR_HAS_FORK
355 abts_run_test(suite, rand_fork, NULL);
356 #endif
357
358 return suite;
359 }
360