1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/* random.c: random huge generator for Linux and other unix's
This has nothing to do with cryptography.
Copyright (C) 1998 Paul Sheer
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "mostincludes.h"
#include "huge-number.h"
#include "random.h"
#include "md5.h"
#include "diffie/compat.h"
#define INTS_RANDOM_SOURCE (8)
#define CHARS_RANDOM_SOURCE (INTS_RANDOM_SOURCE * (sizeof (unsigned int)))
#define CHARS_MD5_HASH (128 / 8)
#ifdef __linux__
/* returns at least n chars. result must be free'd */
char *get_random_chars (int n)
{
char *s, *t;
int f;
f = open ("/dev/urandom", O_RDONLY);
if (f <= 0) {
fprintf (stderr, "random.c: cannot open /dev/urandom: use mknod to create this\ndevice. See /usr/src/linux/drivers/char/random.c\n");
abort ();
}
t = s = malloc (n);
while (n) {
int count;
count = read (f, t, n);
if (count < 0 && errno == EINTR)
continue;
if (count <= 0) {
fprintf (stderr, "random.c: error reading /dev/urandom\n");
abort ();
}
n -= count;
t += count;
}
close (f);
return s;
}
#else
/* returns at least n chars. result must be free'd */
char *get_random_chars (int n)
{
/* Heres a made-up way to get a random sequence. I think its unsafe personally */
char *r, *s, *t;
struct stat st;
unsigned int x[INTS_RANDOM_SOURCE];
int i;
x[0] = time (0);
x[1] = getpid ();
x[2] = getppid ();
stat ("/tmp", &st);
x[3] = st.st_atime;
x[4] = st.st_mtime;
stat ("/etc", &st);
x[5] = st.st_atime;
x[6] = st.st_mtime;
x[7] = clock ();
s = malloc (n + CHARS_MD5_HASH);
t = md5_hash ((const char *) x, CHARS_RANDOM_SOURCE);
memcpy (s, t, CHARS_MD5_HASH);
for (i = 0; i < n; i += CHARS_MD5_HASH) {
r = t;
t = md5_hash (r, CHARS_MD5_HASH);
free (r);
memcpy (s + i, t, CHARS_MD5_HASH);
}
free (t);
return s;
}
#endif
/* size must be a multiple of 8 bits */
Huge *get_random_huge (int size)
{
char *r;
Huge *z;
size /= 8;
r = get_random_chars (size);
z = huge_from_binary ((unsigned char *) r, size);
free (r);
return z;
}
|