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 27static 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 48static apr_random_t *r; 49 50typedef apr_status_t APR_THREAD_FUNC rnd_fn(apr_random_t * r, void *b, 51 apr_size_t n); 52 53static 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 71static 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 99static 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 106static 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 119static 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 125static 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 150static void rand_seed_short2(abts_case *tc, void *data) 151{ 152 rand_run_seed_short(tc, apr_random_secure_bytes, r, 320); 153} 154 155static 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 180static 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 186static 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 210static 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 236static 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 327static 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 342abts_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