1 /** $MirOS: src/lib/libdes/rnd_keys.c,v 1.2 2005/03/06 20:29:00 tg Exp $ */
2 /* $OpenBSD: rnd_keys.c,v 1.2 2000/03/02 00:29:48 todd Exp $ */
3
4 /* Copyright (C) 1993 Eric Young - see COPYING for more details */
5 #include "des_locl.h"
6 #include <sys/time.h>
7
8 #include <unistd.h>
9
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <netdb.h>
13
14 /*
15 * Create a sequence of random 64 bit blocks.
16 * The sequence is indexed with a long long and
17 * based on an initial des key used as a seed.
18 */
19 static des_key_schedule sequence_seed;
20 static u_int32_t sequence_index[2];
21
22 /*
23 * In case the generator does not get inited use this for backup.
24 */
25 static int initialized;
26 static des_cblock default_seed = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
27 static void
do_initialize()28 do_initialize()
29 {
30 des_set_odd_parity(&default_seed);
31 des_set_random_generator_seed(&default_seed);
32 }
33
34 #define zero_long_long(ll) do { ll[0] = ll[1] = 0; } while (0)
35
36 #define incr_long_long(ll) do { if (++ll[0] == 0) ++ll[1]; } while (0)
37
38 #define des_set_sequence_number(ll) \
39 do { \
40 memcpy((char *)sequence_index, (ll), sizeof(sequence_index)); \
41 } while (0)
42
43 #define des_generate_random_block(ret) \
44 do { \
45 des_ecb_encrypt((des_cblock *) sequence_index, (ret), sequence_seed, DES_ENCRYPT); \
46 incr_long_long(sequence_index); \
47 } while (0)
48
49 void
des_set_random_generator_seed(des_cblock * seed)50 des_set_random_generator_seed(des_cblock *seed)
51 {
52 des_key_sched(seed, sequence_seed);
53 zero_long_long(sequence_index);
54 initialized = 1;
55 }
56
57 /*
58 * Generate a sequence of random des keys
59 * using the random block sequence, fixup
60 * parity and skip weak keys.
61 */
62 int
des_new_random_key(des_cblock * key)63 des_new_random_key(des_cblock *key)
64 {
65 if (!initialized)
66 do_initialize();
67
68 try_again:
69 des_generate_random_block(key);
70 /* random key must have odd parity and not be weak */
71 des_set_odd_parity(key);
72 if (des_is_weak_key(key))
73 goto try_again;
74 return(0);
75 }
76
77 /*
78 * des_init_random_number_generator:
79 *
80 * This routine takes a secret key possibly shared by a number
81 * of servers and uses it to generate a random number stream that is
82 * not shared by any of the other servers. It does this by using the current
83 * process id, host id, and the current time to the nearest second. The
84 * resulting stream seed is not useful information for cracking the secret
85 * key. Moreover, this routine keeps no copy of the secret key.
86 *
87 */
88 void
des_init_random_number_generator(des_cblock * seed)89 des_init_random_number_generator(des_cblock *seed)
90 {
91 struct timeval now;
92 static long uniq[2];
93 des_cblock new_key;
94 long gethostid(void);
95
96 gettimeofday(&now, (struct timezone *)0);
97 if (!uniq[0])
98 {
99 struct hostent *hent;
100 char hostname[100];
101 gethostname(hostname, sizeof(hostname));
102 hent = gethostbyname(hostname);
103 if (hent != NULL)
104 memmove(&uniq[0], hent->h_addr_list[0], sizeof(uniq[0]));
105 else
106 uniq[0] = gethostid();
107 #ifdef MSDOS
108 uniq[1] = 1;
109 #else
110 uniq[1] = getpid();
111 #endif
112 }
113
114 /* Pick a unique random key from the shared sequence. */
115 des_set_random_generator_seed(seed);
116 des_set_sequence_number((unsigned char *)uniq);
117 des_new_random_key(&new_key);
118
119 /* Select a new nonshared sequence, */
120 des_set_random_generator_seed(&new_key);
121
122 /* and use the current time to pick a key for the new sequence. */
123 des_set_sequence_number((unsigned char *)&now);
124 des_new_random_key(&new_key);
125 des_set_random_generator_seed(&new_key);
126 }
127