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_random.h"
19#include "apr_thread_proc.h"
20#include <stdio.h>
21#include <stdlib.h>
22#include "testutil.h"
23
24static void hexdump(const unsigned char *b, int n)
25{
26    int i;
27
28    for (i = 0; i < n; ++i) {
29#if 0
30        if ((i & 0xf) == 0)
31            printf("%04x", i);
32        printf(" %02x", b[i]);
33        if ((i & 0xf) == 0xf)
34            printf("\n");
35#else
36        printf("0x%02x,", b[i]);
37        if ((i & 7) == 7)
38            printf("\n");
39#endif
40    }
41    printf("\n");
42}
43
44static apr_random_t *r;
45
46typedef apr_status_t APR_THREAD_FUNC rnd_fn(apr_random_t * r, void *b,
47                                            apr_size_t n);
48
49static void rand_run_kat(abts_case *tc, rnd_fn *f, apr_random_t *r,
50                         const unsigned char expected[128])
51{
52    unsigned char c[128];
53    apr_status_t rv;
54
55    rv = f(r, c, 128);
56    ABTS_INT_EQUAL(tc, 0, rv);
57    if (rv)
58        return;
59    if (memcmp(c, expected, 128)) {
60        hexdump(c, 128);
61        hexdump(expected, 128);
62        ABTS_FAIL(tc, "Randomness mismatch");
63    }
64}
65
66#if APR_HAS_FORK
67static int rand_check_kat(rnd_fn *f, apr_random_t *r,
68                          const unsigned char expected[128])
69{
70    unsigned char c[128];
71    apr_status_t rv;
72
73    rv = f(r, c, 128);
74    if (rv)
75        return 2;
76    if (memcmp(c, expected, 128))
77        return 1;
78    return 0;
79}
80#endif
81
82static void rand_add_zeroes(apr_random_t *r)
83{
84    static unsigned char c[2048];
85
86    apr_random_add_entropy(r, c, sizeof c);
87}
88
89static void rand_run_seed_short(abts_case *tc, rnd_fn *f, apr_random_t *r,
90                                int count)
91{
92    int i;
93    apr_status_t rv;
94    char c[1];
95
96    for (i = 0; i < count; ++i)
97        rand_add_zeroes(r);
98    rv = f(r, c, 1);
99    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTENOUGHENTROPY(rv));
100}
101
102static void rand_seed_short(abts_case *tc, void *data)
103{
104    r = apr_random_standard_new(p);
105    rand_run_seed_short(tc, apr_random_insecure_bytes, r, 32);
106}
107
108static void rand_kat(abts_case *tc, void *data)
109{
110    unsigned char expected[128] = {
111        0x82, 0x04, 0xad, 0xd2, 0x0b, 0xd5, 0xac, 0xda,
112        0x3d, 0x85, 0x58, 0x38, 0x54, 0x6b, 0x69, 0x45,
113        0x37, 0x4c, 0xc7, 0xd7, 0x87, 0xeb, 0xbf, 0xd9,
114        0xb1, 0xb8, 0xb8, 0x2d, 0x9b, 0x33, 0x6e, 0x97,
115        0x04, 0x1d, 0x4c, 0xb0, 0xd1, 0xdf, 0x3d, 0xac,
116        0xd2, 0xaa, 0xfa, 0xcd, 0x96, 0xb7, 0xcf, 0xb1,
117        0x8e, 0x3d, 0xb3, 0xe5, 0x37, 0xa9, 0x95, 0xb4,
118        0xaa, 0x3d, 0x11, 0x1a, 0x08, 0x20, 0x21, 0x9f,
119        0xdb, 0x08, 0x3a, 0xb9, 0x57, 0x9f, 0xf2, 0x1f,
120        0x27, 0xdc, 0xb6, 0xc0, 0x85, 0x08, 0x05, 0xbb,
121        0x13, 0xbe, 0xb1, 0xe9, 0x63, 0x2a, 0xe2, 0xa4,
122        0x23, 0x15, 0x2a, 0x10, 0xbf, 0xdf, 0x09, 0xb3,
123        0xc7, 0xfb, 0x2d, 0x87, 0x48, 0x19, 0xfb, 0xc0,
124        0x15, 0x8c, 0xcb, 0xc6, 0xbd, 0x89, 0x38, 0x69,
125        0xa3, 0xae, 0xa3, 0x21, 0x58, 0x50, 0xe7, 0xc4,
126        0x87, 0xec, 0x2e, 0xb1, 0x2d, 0x6a, 0xbd, 0x46
127    };
128
129    rand_add_zeroes(r);
130    rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
131}
132
133static void rand_seed_short2(abts_case *tc, void *data)
134{
135    rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
136}
137
138static void rand_kat2(abts_case *tc, void *data)
139{
140    unsigned char expected[128] = {
141        0x38, 0x8f, 0x01, 0x29, 0x5a, 0x5c, 0x1f, 0xa8,
142        0x00, 0xde, 0x16, 0x4c, 0xe5, 0xf7, 0x1f, 0x58,
143        0xc0, 0x67, 0xe2, 0x98, 0x3d, 0xde, 0x4a, 0x75,
144        0x61, 0x3f, 0x23, 0xd8, 0x45, 0x7a, 0x10, 0x60,
145        0x59, 0x9b, 0xd6, 0xaf, 0xcb, 0x0a, 0x2e, 0x34,
146        0x9c, 0x39, 0x5b, 0xd0, 0xbc, 0x9a, 0xf0, 0x7b,
147        0x7f, 0x40, 0x8b, 0x33, 0xc0, 0x0e, 0x2a, 0x56,
148        0xfc, 0xe5, 0xab, 0xde, 0x7b, 0x13, 0xf5, 0xec,
149        0x15, 0x68, 0xb8, 0x09, 0xbc, 0x2c, 0x15, 0xf0,
150        0x7b, 0xef, 0x2a, 0x97, 0x19, 0xa8, 0x69, 0x51,
151        0xdf, 0xb0, 0x5f, 0x1a, 0x4e, 0xdf, 0x42, 0x02,
152        0x71, 0x36, 0xa7, 0x25, 0x64, 0x85, 0xe2, 0x72,
153        0xc7, 0x87, 0x4d, 0x7d, 0x15, 0xbb, 0x15, 0xd1,
154        0xb1, 0x62, 0x0b, 0x25, 0xd9, 0xd3, 0xd9, 0x5a,
155        0xe3, 0x47, 0x1e, 0xae, 0x67, 0xb4, 0x19, 0x9e,
156        0xed, 0xd2, 0xde, 0xce, 0x18, 0x70, 0x57, 0x12
157    };
158
159    rand_add_zeroes(r);
160    rand_run_kat(tc, apr_random_secure_bytes, r, expected);
161}
162
163static void rand_barrier(abts_case *tc, void *data)
164{
165    apr_random_barrier(r);
166    rand_run_seed_short(tc, apr_random_secure_bytes, r, 320);
167}
168
169static void rand_kat3(abts_case *tc, void *data)
170{
171    unsigned char expected[128] = {
172        0xe8, 0xe7, 0xc9, 0x45, 0xe2, 0x2a, 0x54, 0xb2,
173        0xdd, 0xe0, 0xf9, 0xbc, 0x3d, 0xf9, 0xce, 0x3c,
174        0x4c, 0xbd, 0xc9, 0xe2, 0x20, 0x4a, 0x35, 0x1c,
175        0x04, 0x52, 0x7f, 0xb8, 0x0f, 0x60, 0x89, 0x63,
176        0x8a, 0xbe, 0x0a, 0x44, 0xac, 0x5d, 0xd8, 0xeb,
177        0x24, 0x7d, 0xd1, 0xda, 0x4d, 0x86, 0x9b, 0x94,
178        0x26, 0x56, 0x4a, 0x5e, 0x30, 0xea, 0xd4, 0xa9,
179        0x9a, 0xdf, 0xdd, 0xb6, 0xb1, 0x15, 0xe0, 0xfa,
180        0x28, 0xa4, 0xd6, 0x95, 0xa4, 0xf1, 0xd8, 0x6e,
181        0xeb, 0x8c, 0xa4, 0xac, 0x34, 0xfe, 0x06, 0x92,
182        0xc5, 0x09, 0x99, 0x86, 0xdc, 0x5a, 0x3c, 0x92,
183        0xc8, 0x3e, 0x52, 0x00, 0x4d, 0x01, 0x43, 0x6f,
184        0x69, 0xcf, 0xe2, 0x60, 0x9c, 0x23, 0xb3, 0xa5,
185        0x5f, 0x51, 0x47, 0x8c, 0x07, 0xde, 0x60, 0xc6,
186        0x04, 0xbf, 0x32, 0xd6, 0xdc, 0xb7, 0x31, 0x01,
187        0x29, 0x51, 0x51, 0xb3, 0x19, 0x6e, 0xe4, 0xf8
188    };
189
190    rand_run_kat(tc, apr_random_insecure_bytes, r, expected);
191}
192
193static void rand_kat4(abts_case *tc, void *data)
194{
195    unsigned char expected[128] = {
196        0x7d, 0x0e, 0xc4, 0x4e, 0x3e, 0xac, 0x86, 0x50,
197        0x37, 0x95, 0x7a, 0x98, 0x23, 0x26, 0xa7, 0xbf,
198        0x60, 0xfb, 0xa3, 0x70, 0x90, 0xc3, 0x58, 0xc6,
199        0xbd, 0xd9, 0x5e, 0xa6, 0x77, 0x62, 0x7a, 0x5c,
200        0x96, 0x83, 0x7f, 0x80, 0x3d, 0xf4, 0x9c, 0xcc,
201        0x9b, 0x0c, 0x8c, 0xe1, 0x72, 0xa8, 0xfb, 0xc9,
202        0xc5, 0x43, 0x91, 0xdc, 0x9d, 0x92, 0xc2, 0xce,
203        0x1c, 0x5e, 0x36, 0xc7, 0x87, 0xb1, 0xb4, 0xa3,
204        0xc8, 0x69, 0x76, 0xfc, 0x35, 0x75, 0xcb, 0x08,
205        0x2f, 0xe3, 0x98, 0x76, 0x37, 0x80, 0x04, 0x5c,
206        0xb8, 0xb0, 0x7f, 0xb2, 0xda, 0xe3, 0xa3, 0xba,
207        0xed, 0xff, 0xf5, 0x9d, 0x3b, 0x7b, 0xf3, 0x32,
208        0x6c, 0x50, 0xa5, 0x3e, 0xcc, 0xe1, 0x84, 0x9c,
209        0x17, 0x9e, 0x80, 0x64, 0x09, 0xbb, 0x62, 0xf1,
210        0x95, 0xf5, 0x2c, 0xc6, 0x9f, 0x6a, 0xee, 0x6d,
211        0x17, 0x35, 0x5f, 0x35, 0x8d, 0x55, 0x0c, 0x07
212    };
213
214    rand_add_zeroes(r);
215    rand_run_kat(tc, apr_random_secure_bytes, r, expected);
216}
217
218#if APR_HAS_FORK
219static void rand_fork(abts_case *tc, void *data)
220{
221    apr_proc_t proc;
222    apr_status_t rv;
223    unsigned char expected[128] = {
224        0xac, 0x93, 0xd2, 0x5c, 0xc7, 0xf5, 0x8d, 0xc2,
225        0xd8, 0x8d, 0xb6, 0x7a, 0x94, 0xe1, 0x83, 0x4c,
226        0x26, 0xe2, 0x38, 0x6d, 0xf5, 0xbd, 0x9d, 0x6e,
227        0x91, 0x77, 0x3a, 0x4b, 0x9b, 0xef, 0x9b, 0xa3,
228        0x9f, 0xf6, 0x6d, 0x0c, 0xdc, 0x4b, 0x02, 0xe9,
229        0x5d, 0x3d, 0xfc, 0x92, 0x6b, 0xdf, 0xc9, 0xef,
230        0xb9, 0xa8, 0x74, 0x09, 0xa3, 0xff, 0x64, 0x8d,
231        0x19, 0xc1, 0x31, 0x31, 0x17, 0xe1, 0xb7, 0x7a,
232        0xe7, 0x55, 0x14, 0x92, 0x05, 0xe3, 0x1e, 0xb8,
233        0x9b, 0x1b, 0xdc, 0xac, 0x0e, 0x15, 0x08, 0xa2,
234        0x93, 0x13, 0xf6, 0x04, 0xc6, 0x9d, 0xf8, 0x7f,
235        0x26, 0x32, 0x68, 0x43, 0x2e, 0x5a, 0x4f, 0x47,
236        0xe8, 0xf8, 0x59, 0xb7, 0xfb, 0xbe, 0x30, 0x04,
237        0xb6, 0x63, 0x6f, 0x19, 0xf3, 0x2c, 0xd4, 0xeb,
238        0x32, 0x8a, 0x54, 0x01, 0xd0, 0xaf, 0x3f, 0x13,
239        0xc1, 0x7f, 0x10, 0x2e, 0x08, 0x1c, 0x28, 0x4b,
240    };
241
242    rv = apr_proc_fork(&proc, p);
243    if (rv == APR_INCHILD) {
244        int n = rand_check_kat(apr_random_secure_bytes, r, expected);
245        exit(n);
246    }
247    else if (rv == APR_INPARENT) {
248        int exitcode;
249        apr_exit_why_e why;
250
251        rand_run_kat(tc, apr_random_secure_bytes, r, expected);
252        apr_proc_wait(&proc, &exitcode, &why, APR_WAIT);
253        if (why != APR_PROC_EXIT) {
254            ABTS_FAIL(tc, "Child terminated abnormally");
255        }
256        else if (exitcode == 0) {
257            ABTS_FAIL(tc, "Child produced our randomness");
258        }
259        else if (exitcode == 2) {
260            ABTS_FAIL(tc, "Child randomness failed");
261        }
262        else if (exitcode != 1) {
263            ABTS_FAIL(tc, "Uknown child error");
264        }
265    } else {
266        ABTS_FAIL(tc, "Fork failed");
267    }
268}
269#endif
270
271static void rand_exists(abts_case *tc, void *data)
272{
273#if !APR_HAS_RANDOM
274    ABTS_NOT_IMPL(tc, "apr_generate_random_bytes");
275#else
276    unsigned char c[42];
277
278    /* There must be a better way to test random-ness, but I don't know
279     * what it is right now.
280     */
281    APR_ASSERT_SUCCESS(tc, "apr_generate_random_bytes failed",
282                       apr_generate_random_bytes(c, sizeof c));
283#endif
284}
285
286abts_suite *testrand(abts_suite *suite)
287{
288    suite = ADD_SUITE(suite)
289
290    abts_run_test(suite, rand_exists, NULL);
291    abts_run_test(suite, rand_seed_short, NULL);
292    abts_run_test(suite, rand_kat, NULL);
293    abts_run_test(suite, rand_seed_short2, NULL);
294    abts_run_test(suite, rand_kat2, NULL);
295    abts_run_test(suite, rand_barrier, NULL);
296    abts_run_test(suite, rand_kat3, NULL);
297    abts_run_test(suite, rand_kat4, NULL);
298#if APR_HAS_FORK
299    abts_run_test(suite, rand_fork, NULL);
300#endif
301
302    return suite;
303}
304