]> git.ipfire.org Git - thirdparty/dhcp.git/blob - dst/prandom.c
[master] Corrects medium impact issues reported by Coverity.
[thirdparty/dhcp.git] / dst / prandom.c
1 /*
2 * Portions Copyright (c) 2012-2014 by Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (c) 2007,2009 by Internet Systems Consortium, Inc. ("ISC")
4 * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
5 *
6 * Permission to use, copy modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
11 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
12 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
13 * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
17 * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
18 */
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <time.h>
27 #include <dirent.h>
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/time.h>
31
32 #include <netinet/in.h>
33 #include <sys/socket.h>
34 #define NEED_PRAND_CONF
35
36 #include "cdefs.h"
37 #include "osdep.h"
38 #include "dst_internal.h"
39 #include "arpa/nameser.h"
40
41
42 #ifndef DST_NUM_HASHES
43 #define DST_NUM_HASHES 4
44 #endif
45 #ifndef DST_NUMBER_OF_COUNTERS
46 #define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */
47 #endif
48
49 /*
50 * the constant below is a prime number to make fixed data structures like
51 * stat and time wrap over blocks. This adds certain randomness to what is
52 * in each digested block.
53 * The prime number 2879 has the special property that when
54 * divided by 2,4 and 6 the result is also a prime numbers
55 */
56
57 #ifndef DST_RANDOM_BLOCK_SIZE
58 #define DST_RANDOM_BLOCK_SIZE 2879
59 #endif
60
61 /*
62 * This constant dictates how many bits we shift to the right before using a
63 */
64 #ifndef DST_SHIFT
65 #define DST_SHIFT 9
66 #endif
67
68 /*
69 * An initializer that is as bad as any other with half the bits set
70 */
71 #ifndef DST_RANDOM_PATTERN
72 #define DST_RANDOM_PATTERN 0x8765CA93
73 #endif
74 /*
75 * things must have changed in the last 3600 seconds to be used
76 */
77 #define MAX_OLD 3600
78
79 /*
80 * Define a single set of configuration for prand stuff. A superset
81 * works okay (failed commands return no data, missing directories
82 * are skipped, and so on.
83 */
84 static const char *cmds[] = {
85 "/usr/bin/netstat -an 2>&1",
86 "/usr/sbin/netstat -an 2>&1",
87 "/usr/etc/netstat -an 2>&1",
88 "/bin/netstat -an 2>&1",
89 "/usr/ucb/netstat -an 2>&1",
90
91 /* AIX */
92 "/bin/ps -ef 2>&1",
93 "/bin/df 2>&1",
94 "/usr/bin/uptime 2>&1",
95 "/usr/bin/printenv 2>&1",
96 "/usr/bin/netstat -s 2>&1",
97 "/usr/bin/w 2>&1",
98 /* Tru64 */
99 "/usr/bin/dig com. soa +ti=1 +retry=0 2>&1",
100 "/usr/sbin/arp -an 2>&1",
101 "/usr/ucb/uptime 2>&1",
102 "/bin/iostat 2>&1",
103 /* BSD */
104 "/bin/ps -axlw 2>&1",
105 "/usr/sbin/iostat 2>&1",
106 "/usr/sbin/vmstat 2>&1",
107 /* FreeBSD */
108 "/usr/bin/vmstat 2>&1",
109 "/usr/bin/w 2>&1",
110 /* HP/UX */
111 "/usr/bin/ps -ef 2>&1",
112 /* IRIX */
113 "/usr/etc/arp -a 2>&1",
114 "/usr/bsd/uptime 2>&1",
115 "/usr/bin/printenv 2>&1",
116 "/usr/bsd/w 2>&1",
117 /* Linux */
118 "/sbin/arp -an 2>&1",
119 "/usr/bin/vmstat 2>&1",
120 /* NetBSD */
121 /* OpenBSD */
122 /* QNX */
123 "/bin/ps -a 2>&1",
124 "/bin/sin 2>&1",
125 "/bin/sin fds 2>&1",
126 "/bin/sin memory 2>&1",
127 /* Solaris */
128 "/usr/ucb/uptime 2>&1",
129 "/usr/ucb/netstat -an 2>&1",
130
131 "/usr/bin/netstat -an 2>&1",
132 "/usr/sbin/netstat -an 2>&1",
133 "/usr/etc/netstat -an 2>&1",
134 "/bin/netstat -an 2>&1",
135 "/usr/ucb/netstat -an 2>&1",
136 NULL
137 };
138
139 static const char *dirs[] = {
140 "/tmp",
141 "/var/tmp",
142 ".",
143 "/",
144 "/var/spool",
145 "/var/adm",
146 "/dev",
147 "/var/spool/mail",
148 "/var/mail",
149 "/home",
150 "/usr/home",
151 NULL
152 };
153
154 static const char *files[] = {
155 "/var/adm/messages",
156 "/var/adm/wtmp",
157 "/var/adm/lastlog",
158 "/var/log/messages",
159 "/var/log/wtmp",
160 "/var/log/lastlog",
161 "/proc/stat",
162 "/proc/rtc",
163 "/proc/meminfo",
164 "/proc/interrupts",
165 "/proc/self/status",
166 "/proc/ipstats",
167 "/proc/dumper",
168 "/proc/self/as",
169 NULL
170 };
171
172 /*
173 * these two data structure are used to process input data into digests,
174 *
175 * The first structure contains a pointer to a DST HMAC key
176 * the variables accompanying are used for
177 * step : select every step byte from input data for the hash
178 * block: number of data elements going into each hash
179 * digested: number of data elements digested so far
180 * curr: offset into the next input data for the first byte.
181 */
182 typedef struct hash {
183 DST_KEY *key;
184 void *ctx;
185 int digested, block, step, curr;
186 } prand_hash;
187
188 /*
189 * This data structure controls number of hashes and keeps track of
190 * overall progress in generating correct number of bytes of output.
191 * output : array to store the output data in
192 * needed : how many bytes of output are needed
193 * filled : number of bytes in output so far.
194 * bytes : total number of bytes processed by this structure
195 * file_digest : the HMAC key used to digest files.
196 */
197 typedef struct work {
198 unsigned needed, filled, bytes;
199 u_char *output;
200 prand_hash *hash[DST_NUM_HASHES];
201 DST_KEY *file_digest;
202 } dst_work;
203
204
205 /*
206 * forward function declarations
207 */
208 static int get_dev_random(u_char *output, unsigned size);
209 static int do_time(dst_work *work);
210 static int do_ls(dst_work *work);
211 static int unix_cmd(dst_work *work);
212 static int digest_file(dst_work *work);
213
214 static void force_hash(dst_work *work, prand_hash *hash);
215 static int do_hash(dst_work *work, prand_hash *hash, const u_char *input,
216 unsigned size);
217 static int my_digest(dst_work *tmp, const u_char *input, unsigned size);
218 static prand_hash *get_hmac_key(int step, int block);
219
220 static unsigned own_random(dst_work *work);
221
222
223 /*
224 * variables used in the quick random number generator
225 */
226 static u_int32_t ran_val = DST_RANDOM_PATTERN;
227 static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10);
228
229 /*
230 * setting the quick_random generator to particular values or if both
231 * input parameters are 0 then set it to initial values
232 */
233
234 void
235 dst_s_quick_random_set(u_int32_t val, u_int32_t cnt)
236 {
237 ran_val = (val == 0) ? DST_RANDOM_PATTERN : val;
238 ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt;
239 }
240
241 /*
242 * this is a quick and random number generator that seems to generate quite
243 * good distribution of data
244 */
245 u_int32_t
246 dst_s_quick_random(int inc)
247 {
248 ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^
249 ((ran_val >> 7) ^ (ran_val << 25));
250 if (inc > 0) /* only increasing values accepted */
251 ran_cnt += inc;
252 ran_val += ran_cnt++;
253 return (ran_val);
254 }
255
256 /*
257 * get_dev_random: Function to read /dev/random reliably
258 * this function returns how many bytes where read from the device.
259 * port_after.h should set the control variable HAVE_DEV_RANDOM
260 */
261 static int
262 get_dev_random(u_char *output, unsigned size)
263 {
264 #ifdef HAVE_DEV_RANDOM
265 struct stat st;
266 int n = 0, fd = -1, s;
267
268 s = stat("/dev/random", &st);
269 if (s == 0 && S_ISCHR(st.st_mode)) {
270 if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) {
271 if ((n = read(fd, output, size)) < 0)
272 n = 0;
273 close(fd);
274 }
275 return (n);
276 }
277 #endif
278 return (0);
279 }
280
281 /*
282 * Portable way of getting the time values if gettimeofday is missing
283 * then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but
284 * gettimeofday() is not.
285 * Time of day is predictable, we are looking for the randomness that comes
286 * the last few bits in the microseconds in the timer are hard to predict when
287 * this is invoked at the end of other operations
288 */
289 struct timeval *mtime;
290 static int
291 do_time(dst_work *work)
292 {
293 int cnt = 0;
294 static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)];
295 struct timezone *zone;
296
297 zone = (struct timezone *) tmp;
298 mtime = (struct timeval *)(tmp + sizeof(struct timezone));
299 gettimeofday(mtime, zone);
300 cnt = sizeof(tmp);
301 my_digest(work, tmp, sizeof(tmp));
302
303 return (cnt);
304 }
305
306 /*
307 * this function simulates the ls command, but it uses stat which gives more
308 * information and is harder to guess
309 * Each call to this function will visit the next directory on the list of
310 * directories, in a circular manner.
311 * return value is the number of bytes added to the temp buffer
312 *
313 * do_ls() does not visit subdirectories
314 * if attacker has access to machine it can guess most of the values seen
315 * thus it is important to only visit directories that are frequently updated
316 * Attacker that has access to the network can see network traffic
317 * when NFS mounted directories are accessed and know exactly the data used
318 * but may not know exactly in what order data is used.
319 * Returns the number of bytes that where returned in stat structures
320 */
321 static int
322 do_ls(dst_work *work)
323 {
324 struct dir_info {
325 uid_t uid;
326 gid_t gid;
327 off_t size;
328 time_t atime, mtime, ctime;
329 };
330 static struct dir_info dir_info;
331 struct stat buf;
332 struct dirent *entry;
333 static int i = 0;
334 static unsigned long d_round = 0;
335 struct timeval tv;
336 int n = 0, out = 0;
337 unsigned dir_len;
338
339 char file_name[1024];
340 u_char tmp_buff[1024];
341 DIR *dir = NULL;
342
343 if (dirs[i] == NULL) /* if at the end of the list start over */
344 i = 0;
345 if (stat(dirs[i++], &buf)) /* directory does not exist */
346 return (0);
347
348 gettimeofday(&tv,NULL);
349 if (d_round == 0)
350 d_round = tv.tv_sec - MAX_OLD;
351 else if (i==1) /* if starting a new round cut what we accept */
352 d_round += (tv.tv_sec - d_round)/2;
353
354 if (buf.st_atime < d_round)
355 return (0);
356
357 EREPORT(("do_ls i %d filled %4d in_temp %4d\n",
358 i-1, work->filled, work->in_temp));
359 memcpy(tmp_buff, &buf, sizeof(buf));
360
361
362 if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */
363 return (0);
364 strcpy(file_name, dirs[i-1]);
365 dir_len = strlen(file_name);
366 file_name[dir_len++] = '/';
367 while ((entry = readdir(dir))) {
368 unsigned len = strlen(entry->d_name);
369 out += len;
370 if (my_digest(work, (u_char *)entry->d_name, len))
371 break;
372
373 memcpy(&file_name[dir_len], entry->d_name, len);
374 file_name[dir_len + len] = 0x0;
375 /* for all entries in dir get the stats */
376 if (stat(file_name, &buf) == 0) {
377 n++; /* count successful stat calls */
378 /* copy non static fields */
379 dir_info.uid += buf.st_uid;
380 dir_info.gid += buf.st_gid;
381 dir_info.size += buf.st_size;
382 dir_info.atime += buf.st_atime;
383 dir_info.mtime += buf.st_mtime;
384 dir_info.ctime += buf.st_ctime;
385 out += sizeof(dir_info);
386 if(my_digest(work, (u_char *)&dir_info,
387 sizeof(dir_info)))
388 break;
389 }
390 }
391 closedir(dir); /* done */
392 out += do_time(work); /* add a time stamp */
393 return (out);
394 }
395
396
397 /*
398 * unix_cmd()
399 * this function executes the a command from the cmds[] list of unix commands
400 * configured in the prand_conf.h file
401 * return value is the number of bytes added to the randomness temp buffer
402 *
403 * it returns the number of bytes that where read in
404 * if more data is needed at the end time is added to the data.
405 * This function maintains a state to selects the next command to run
406 * returns the number of bytes read in from the command
407 */
408 static int
409 unix_cmd(dst_work *work)
410 {
411 static int cmd_index = 0;
412 int cnt = 0, n;
413 FILE *pipe;
414 u_char buffer[4096];
415
416 if (cmds[cmd_index] == NULL)
417 cmd_index = 0;
418 EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n",
419 cmd_index, work->filled, work->in_temp));
420 pipe = popen(cmds[cmd_index++], "r"); /* execute the command */
421
422 while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) {
423 cnt += n; /* process the output */
424 if (my_digest(work, buffer, (unsigned)n))
425 break;
426 /* this adds some randomness to the output */
427 cnt += do_time(work);
428 }
429 while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0)
430 ; /* drain the pipe */
431 pclose(pipe);
432 return (cnt); /* read how many bytes where read in */
433 }
434
435 /*
436 * digest_file() This function will read a file and run hash over it
437 * input is a file name
438 */
439 static int
440 digest_file(dst_work *work)
441 {
442 static int f_cnt = 0;
443 static unsigned long f_round = 0;
444 FILE *fp;
445 void *ctx;
446 const char *name;
447 int no, i;
448 struct stat st;
449 struct timeval tv;
450 u_char buf[1024];
451
452 name = files[f_cnt++];
453 if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL)
454 if (gettimeofday(&tv, NULL)) /* only do this if needed */
455 return (0);
456 if (f_round == 0) /* first time called set to one hour ago */
457 f_round = (tv.tv_sec - MAX_OLD);
458 if (files[f_cnt] == NULL) { /* end of list of files */
459 if(f_cnt <= 1) /* list is too short */
460 return (0);
461 f_cnt = 0; /* start again on list */
462 f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */
463 work->file_digest = dst_free_key(work->file_digest);
464 }
465 if (work->file_digest == NULL) {
466 work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0,
467 (u_char *)&tv, sizeof(tv));
468 if (work->file_digest == NULL)
469 return (0);
470 }
471 if (access(name, R_OK) || stat(name, &st))
472 return (0); /* no such file or not allowed to read it */
473 if (strncmp(name, "/proc/", 6) && st.st_mtime < f_round)
474 return(0); /* file has not changed recently enough */
475 if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx,
476 NULL, 0, NULL, 0)) {
477 work->file_digest = dst_free_key(work->file_digest);
478 return (0);
479 }
480 if ((fp = fopen(name, "r")) == NULL)
481 return (0);
482 for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0;
483 no += i)
484 dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx,
485 buf, (unsigned)i, NULL, 0);
486
487 fclose(fp);
488 if (no >= 64) {
489 i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx,
490 NULL, 0, &work->output[work->filled],
491 DST_HASH_SIZE);
492 if (i > 0)
493 work->filled += i;
494 }
495
496 my_digest(work, (const u_char *)name, strlen(name));
497 return (no + strlen(name));
498 }
499
500 /*
501 * function to perform the FINAL and INIT operation on a hash if allowed
502 */
503 static void
504 force_hash(dst_work *work, prand_hash *hash)
505 {
506 int i = 0;
507
508 /*
509 * if more than half a block then add data to output
510 * otherwise add the digest to the next hash
511 */
512 if ((hash->digested * 2) > hash->block) {
513 i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx,
514 NULL, 0, &work->output[work->filled],
515 DST_HASH_SIZE);
516
517 hash->digested = 0;
518 dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx,
519 NULL, 0, NULL, 0);
520 if (i > 0)
521 work->filled += i;
522 }
523 return;
524 }
525
526 /*
527 * This function takes the input data does the selection of data specified
528 * by the hash control block.
529 * The step variable in the work structure determines which 1/step bytes
530 * are used,
531 *
532 */
533 static int
534 do_hash(dst_work *work, prand_hash *hash, const u_char *input, unsigned size)
535 {
536 const u_char *tmp = input;
537 u_char *tp, *abuf = (u_char *)0;
538 int i, n;
539 unsigned needed, avail, dig, cnt = size;
540 unsigned tmp_size = 0;
541
542 if (cnt <= 0 || input == NULL)
543 return (0);
544
545 if (hash->step > 1) { /* if using subset of input data */
546 tmp_size = size / hash->step + 2;
547 abuf = tp = malloc(tmp_size);
548 /* no good return code but at least don't step on things */
549 if (tp == NULL) {
550 return (0);
551 }
552 tmp = tp;
553 for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++)
554 *(tp++) = input[i];
555 /* calculate the starting point in the next input set */
556 hash->curr = (hash->step - (i - size)) % hash->step;
557 }
558 /* digest the data in block sizes */
559 for (n = 0; n < cnt; n += needed) {
560 avail = (cnt - n);
561 needed = hash->block - hash->digested;
562 dig = (avail < needed) ? avail : needed;
563 dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx,
564 &tmp[n], dig, NULL, 0);
565 hash->digested += dig;
566 if (hash->digested >= hash->block)
567 force_hash(work, hash);
568 if (work->needed < work->filled) {
569 if (abuf)
570 SAFE_FREE2(abuf, tmp_size);
571 return (1);
572 }
573 }
574 if (tmp_size > 0)
575 SAFE_FREE2(abuf, tmp_size);
576 return (0);
577 }
578
579 /*
580 * Copy data from INPUT for length SIZE into the work-block TMP.
581 * If we fill the work-block, digest it; then,
582 * if work-block needs more data, keep filling with the rest of the input.
583 */
584 static int
585 my_digest(dst_work *work, const u_char *input, unsigned size)
586 {
587
588 int i, full = 0;
589 static unsigned counter;
590
591 counter += size;
592 /* first do each one of the hashes */
593 for (i = 0; i < DST_NUM_HASHES && full == 0; i++)
594 full = do_hash(work, work->hash[i], input, size) +
595 do_hash(work, work->hash[i], (u_char *) &counter,
596 sizeof(counter));
597 /*
598 * if enough data has be generated do final operation on all hashes
599 * that have enough date for that
600 */
601 for (i = 0; full && (i < DST_NUM_HASHES); i++)
602 force_hash(work, work->hash[i]);
603
604 return (full);
605 }
606
607 /*
608 * this function gets some semi random data and sets that as an HMAC key
609 * If we get a valid key this function returns that key initialized
610 * otherwise it returns NULL;
611 */
612 static prand_hash *
613 get_hmac_key(int step, int block)
614 {
615
616 u_char *buff;
617 int temp = 0, n = 0;
618 unsigned size = 70;
619 DST_KEY *new_key = NULL;
620 prand_hash *new = NULL;
621
622 /* use key that is larger than digest algorithms (64) for key size */
623 buff = malloc(size);
624 if (buff == NULL)
625 return (NULL);
626 /* do not memset the allocated memory to get random bytes there */
627 /* time of day is somewhat random especially in the last bytes */
628 gettimeofday((struct timeval *) &buff[n], NULL);
629 n += sizeof(struct timeval);
630
631 /* get some semi random stuff in here stir it with micro seconds */
632 if (n < size) {
633 temp = dst_s_quick_random((int) buff[n - 1]);
634 memcpy(&buff[n], &temp, sizeof(temp));
635 n += sizeof(temp);
636 }
637 /* get the pid of this process and its parent */
638 if (n < size) {
639 temp = (int) getpid();
640 memcpy(&buff[n], &temp, sizeof(temp));
641 n += sizeof(temp);
642 }
643 if (n < size) {
644 temp = (int) getppid();
645 memcpy(&buff[n], &temp, sizeof(temp));
646 n += sizeof(temp);
647 }
648 /* get the user ID */
649 if (n < size) {
650 temp = (int) getuid();
651 memcpy(&buff[n], &temp, sizeof(temp));
652 n += sizeof(temp);
653 }
654 #ifndef GET_HOST_ID_MISSING
655 if (n < size) {
656 temp = (int) gethostid();
657 memcpy(&buff[n], &temp, sizeof(temp));
658 n += sizeof(temp);
659 }
660 #endif
661 /* get some more random data */
662 if (n < size) {
663 temp = dst_s_quick_random((int) buff[n - 1]);
664 memcpy(&buff[n], &temp, sizeof(temp));
665 }
666 /* covert this into a HMAC key */
667 new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size);
668 SAFE_FREE(buff);
669
670 /* get the control structure */
671 if ((new = malloc(sizeof(prand_hash))) == NULL)
672 return (NULL);
673 new->digested = new->curr = 0;
674 new->step = step;
675 new->block = block;
676 new->key = new_key;
677 if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0)) {
678 SAFE_FREE(new);
679 return (NULL);
680 }
681
682 return (new);
683 }
684
685 /*
686 * own_random()
687 * This function goes out and from various sources tries to generate enough
688 * semi random data that a hash function can generate a random data.
689 * This function will iterate between the two main random source sources,
690 * information from programs and directories in random order.
691 * This function return the number of bytes added to the random output buffer.
692 */
693 static unsigned
694 own_random(dst_work *work)
695 {
696 int dir = 0, b;
697 int bytes, n, cmd = 0, dig = 0;
698 /*
699 * now get the initial seed to put into the quick random function from
700 * the address of the work structure
701 */
702 bytes = (int) getpid();
703 /*
704 * proceed while needed
705 */
706 while (work->filled < work->needed) {
707 EREPORT(("own_random r %08x b %6d t %6d f %6d\n",
708 ran_val, bytes, work->in_temp, work->filled));
709 /* pick a random number in the range of 0..7 based on that random number
710 * perform some operations that yield random data
711 */
712 n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07;
713 switch (n) {
714 case 0:
715 case 3:
716 if (sizeof(cmds) > 2 *sizeof(*cmds)) {
717 b = unix_cmd(work);
718 cmd += b;
719 }
720 break;
721
722 case 1:
723 case 7:
724 if (sizeof(dirs) > 2 *sizeof(*dirs)) {
725 b = do_ls(work);
726 dir += b;
727 }
728 break;
729
730 case 4:
731 case 5:
732 /* retry getting data from /dev/random */
733 b = get_dev_random(&work->output[work->filled],
734 work->needed - work->filled);
735 if (b > 0)
736 work->filled += b;
737 break;
738
739 case 6:
740 if (sizeof(files) > 2 * sizeof(*files)) {
741 b = digest_file(work);
742 dig += b;
743 }
744 break;
745
746 case 2:
747 default: /* to make sure we make some progress */
748 work->output[work->filled++] = 0xff &
749 dst_s_quick_random(bytes);
750 b = 1;
751 break;
752 }
753 if (b > 0)
754 bytes += b;
755 }
756 return (work->filled);
757 }
758
759
760 /*
761 * dst_s_random() This function will return the requested number of bytes
762 * of randomness to the caller it will use the best available sources of
763 * randomness.
764 * The current order is to use /dev/random, precalculated randomness, and
765 * finally use some system calls and programs to generate semi random data
766 * that is then digested to generate randomness.
767 * This function is thread safe as each thread uses its own context, but
768 * concurrent treads will affect each other as they update shared state
769 * information.
770 * It is strongly recommended that this function be called requesting a size
771 * that is not a multiple of the output of the hash function used.
772 *
773 * If /dev/random is not available this function is not suitable to generate
774 * large amounts of data, rather it is suitable to seed a pseudo-random
775 * generator
776 * Returns the number of bytes put in the output buffer
777 */
778 int
779 dst_s_random(u_char *output, unsigned size)
780 {
781 int n = 0, i;
782 unsigned s;
783 static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES];
784 static unsigned unused = 0;
785
786 if (size <= 0 || output == NULL)
787 return (0);
788
789 if (size >= 2048)
790 return (-1);
791 /*
792 * Read from /dev/random
793 */
794 n = get_dev_random(output, size);
795 /*
796 * If old data is available and needed use it
797 */
798 if (n < size && unused > 0) {
799 unsigned need = size - n;
800 if (unused <= need) {
801 memcpy(output, old_unused, unused);
802 n += unused;
803 unused = 0;
804 } else {
805 memcpy(output, old_unused, need);
806 n += need;
807 unused -= need;
808 memcpy(old_unused, &old_unused[need], unused);
809 }
810 }
811 /*
812 * If we need more use the simulated randomness here.
813 */
814 if (n < size) {
815 dst_work *my_work = (dst_work *) malloc(sizeof(dst_work));
816 if (my_work == NULL)
817 return (n);
818 my_work->needed = size - n;
819 my_work->filled = 0;
820 my_work->output = (u_char *) malloc(my_work->needed +
821 DST_HASH_SIZE *
822 DST_NUM_HASHES);
823 my_work->file_digest = NULL;
824 if (my_work->output == NULL) {
825 SAFE_FREE(my_work);
826 return (n);
827 }
828 memset(my_work->output, 0x0, my_work->needed);
829 /* allocate upto 4 different HMAC hash functions out of order */
830 #if DST_NUM_HASHES >= 3
831 my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2);
832 #endif
833 #if DST_NUM_HASHES >= 2
834 my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6);
835 #endif
836 #if DST_NUM_HASHES >= 4
837 my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4);
838 #endif
839 my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE);
840 if (my_work->hash[0] == NULL) { /* if failure bail out */
841 for (i = 1; i < DST_NUM_HASHES; i++) {
842 if (my_work->hash[i] != NULL) {
843 dst_free_key(my_work->hash[i]->key);
844 SAFE_FREE(my_work->hash[i]);
845 }
846 }
847 SAFE_FREE(my_work->output);
848 SAFE_FREE(my_work);
849 return (n);
850 }
851 s = own_random(my_work);
852 /* if more generated than needed store it for future use */
853 if (s >= my_work->needed) {
854 EREPORT(("dst_s_random(): More than needed %d >= %d\n",
855 s, my_work->needed));
856 memcpy(&output[n], my_work->output, my_work->needed);
857 n += my_work->needed;
858 /* saving unused data for next time */
859 unused = s - my_work->needed;
860 if (unused > sizeof(old_unused)) {
861 unused = sizeof(old_unused);
862 }
863 memcpy(old_unused, &my_work->output[my_work->needed],
864 unused);
865 } else {
866 /* XXXX This should not happen */
867 EREPORT(("Not enough %d >= %d\n", s, my_work->needed));
868 memcpy(&output[n], my_work->output, s);
869 n += my_work->needed;
870 }
871
872 /* delete the allocated work area */
873 for (i = 0; i < DST_NUM_HASHES; i++) {
874 if (my_work->hash[i] != NULL) {
875 dst_free_key(my_work->hash[i]->key);
876 SAFE_FREE(my_work->hash[i]);
877 }
878 }
879 SAFE_FREE(my_work->output);
880 SAFE_FREE(my_work);
881 }
882 return (n);
883 }
884
885 /*
886 * A random number generator that is fast and strong
887 * this random number generator is based on HASHing data,
888 * the input to the digest function is a collection of <NUMBER_OF_COUNTERS>
889 * counters that is incremented between digest operations
890 * each increment operation amortizes to 2 bits changed in that value
891 * for 5 counters thus the input will amortize to have 10 bits changed
892 * The counters are initially set using the strong random function above
893 * the HMAC key is selected by the same method as the HMAC keys for the
894 * strong random function.
895 * Each set of counters is used for 2^25 operations
896 *
897 * returns the number of bytes written to the output buffer
898 * or negative number in case of error
899 */
900 int
901 dst_s_semi_random(u_char *output, unsigned size)
902 {
903 static u_int32_t counter[DST_NUMBER_OF_COUNTERS];
904 static u_char semi_old[DST_HASH_SIZE];
905 static int semi_loc = 0, cnt = 0;
906 static unsigned hb_size = 0;
907 static DST_KEY *my_key = NULL;
908 prand_hash *hash;
909 unsigned out = 0;
910 unsigned i;
911 int n, res;
912
913 if (output == NULL || size <= 0)
914 return (-2);
915
916 /* check if we need a new key */
917 if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */
918 if (my_key)
919 my_key->dk_func->destroy(my_key);
920 if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL)
921 return (0);
922 my_key = hash->key;
923 /* check if the key works stir the new key using some old random data */
924 hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
925 (u_char *) counter, sizeof(counter),
926 semi_old, sizeof(semi_old));
927 if (hb_size <= 0) {
928 EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n",
929 my_key->dk_alg, hb_size));
930 return (-1);
931 }
932 /* new set the counters to random values */
933 dst_s_random((u_char *) counter, sizeof(counter));
934 cnt = 0;
935 }
936 /* if old data around use it first */
937 if (semi_loc < hb_size) {
938 if (size <= hb_size - semi_loc) { /* need less */
939 memcpy(output, &semi_old[semi_loc], size);
940 semi_loc += size;
941 return (size); /* DONE */
942 } else {
943 out = hb_size - semi_loc;
944 memcpy(output, &semi_old[semi_loc], out);
945 semi_loc += out;
946 }
947 }
948 /* generate more random stuff */
949 while (out < size) {
950 /*
951 * modify at least one bit by incrementing at least one counter
952 * based on the last bit of the last counter updated update
953 * the next one.
954 * minimally this operation will modify at least 1 bit,
955 * amortized 2 bits
956 */
957 for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++)
958 i = (int) counter[n]++;
959
960 res = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
961 (u_char *) counter, hb_size,
962 semi_old, sizeof(semi_old));
963 if (res < 0) {
964 return res;
965 }
966 i = (unsigned) res;
967 if (i != hb_size)
968 EREPORT(("HMAC SIGNATURE FAILURE %d\n", i));
969 cnt++;
970 if (size - out < i) /* Not all data is needed */
971 semi_loc = i = size - out;
972 memcpy(&output[out], semi_old, i);
973 out += i;
974 }
975 return (out);
976 }