summaryrefslogtreecommitdiff
path: root/lib/libdes/rnd_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libdes/rnd_keys.c')
-rw-r--r--lib/libdes/rnd_keys.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/lib/libdes/rnd_keys.c b/lib/libdes/rnd_keys.c
new file mode 100644
index 00000000000..8ab72795667
--- /dev/null
+++ b/lib/libdes/rnd_keys.c
@@ -0,0 +1,125 @@
+/* $Id: rnd_keys.c,v 1.1 1997/06/29 10:24:52 provos Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see COPYING for more details */
+#include "des_locl.h"
+#include <sys/time.h>
+
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+/*
+ * Create a sequence of random 64 bit blocks.
+ * The sequence is indexed with a long long and
+ * based on an initial des key used as a seed.
+ */
+static des_key_schedule sequence_seed;
+static u_int32_t sequence_index[2];
+
+/*
+ * In case the generator does not get inited use this for backup.
+ */
+static int initialized;
+static des_cblock default_seed = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+static void
+do_initialize()
+{
+ des_set_odd_parity(&default_seed);
+ des_set_random_generator_seed(&default_seed);
+}
+
+#define zero_long_long(ll) do { ll[0] = ll[1] = 0; } while (0)
+
+#define incr_long_long(ll) do { if (++ll[0] == 0) ++ll[1]; } while (0)
+
+#define des_set_sequence_number(ll) \
+do { \
+ memcpy((char *)sequence_index, (ll), sizeof(sequence_index)); \
+ } while (0)
+
+#define des_generate_random_block(ret) \
+do { \
+ des_ecb_encrypt((des_cblock *) sequence_index, (ret), sequence_seed, DES_ENCRYPT); \
+ incr_long_long(sequence_index); \
+ } while (0)
+
+void
+des_set_random_generator_seed(des_cblock *seed)
+{
+ des_key_sched(seed, sequence_seed);
+ zero_long_long(sequence_index);
+ initialized = 1;
+}
+
+/*
+ * Generate a sequence of random des keys
+ * using the random block sequence, fixup
+ * parity and skip weak keys.
+ */
+int
+des_new_random_key(des_cblock *key)
+{
+ if (!initialized)
+ do_initialize();
+
+ try_again:
+ des_generate_random_block(key);
+ /* random key must have odd parity and not be weak */
+ des_set_odd_parity(key);
+ if (des_is_weak_key(key))
+ goto try_again;
+ return(0);
+}
+
+/*
+ * des_init_random_number_generator:
+ *
+ * This routine takes a secret key possibly shared by a number
+ * of servers and uses it to generate a random number stream that is
+ * not shared by any of the other servers. It does this by using the current
+ * process id, host id, and the current time to the nearest second. The
+ * resulting stream seed is not useful information for cracking the secret
+ * key. Moreover, this routine keeps no copy of the secret key.
+ *
+ */
+void
+des_init_random_number_generator(des_cblock *seed)
+{
+ struct timeval now;
+ static long uniq[2];
+ des_cblock new_key;
+ long gethostid(void);
+
+ gettimeofday(&now, (struct timezone *)0);
+ if (!uniq[0])
+ {
+ struct hostent *hent;
+ char hostname[100];
+ gethostname(hostname, sizeof(hostname));
+ hent = gethostbyname(hostname);
+ if (hent != NULL)
+ bcopy(hent->h_addr_list[0], &uniq[0], sizeof(uniq[0]));
+ else
+ uniq[0] = gethostid();
+#ifdef MSDOS
+ uniq[1] = 1;
+#else
+ uniq[1] = getpid();
+#endif
+ }
+
+ /* Pick a unique random key from the shared sequence. */
+ des_set_random_generator_seed(seed);
+ des_set_sequence_number((unsigned char *)uniq);
+ des_new_random_key(&new_key);
+
+ /* Select a new nonshared sequence, */
+ des_set_random_generator_seed(&new_key);
+
+ /* and use the current time to pick a key for the new sequence. */
+ des_set_sequence_number((unsigned char *)&now);
+ des_new_random_key(&new_key);
+ des_set_random_generator_seed(&new_key);
+}