2 * lib/crypto/des/new_rn_key.c
4 * Copyright 1988,1990 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
24 * New pseudo-random key generator, using DES encryption to make the
25 * pseudo-random cycle as hard to break as DES.
27 * Written by Mark Lillibridge, MIT Project Athena
29 * Under U.S. law, this software may not be exported outside the US
30 * without license from the U.S. Commerce department.
37 #define min(a,b) (((a) < (b)) ? (a) : (b))
41 * mit_des_new_random_key: create a random des key
43 * Requires: mit_des_set_random_number_generater_seed must be at called least
44 * once before this routine is called.
46 * Notes: the returned key has correct parity and is guarenteed not
47 * to be a weak des key. Mit_Des_generate_random_block is used to
48 * provide the random bits.
51 mit_des_new_random_key(key, p_seed)
53 mit_des_random_key_seed *p_seed;
56 mit_des_generate_random_block(key, p_seed);
57 mit_des_fixup_key_parity(key);
58 } while (mit_des_is_weak_key(key));
64 * mit_des_init_random_number_generator:
66 * This routine takes a secret key possibly shared by a number
67 * of servers and uses it to generate a random number stream that is
68 * not shared by any of the other servers. It does this by using the current
69 * process id, host id, and the current time to the nearest second. The
70 * resulting stream seed is not useful information for cracking the secret
71 * key. Moreover, this routine keeps no copy of the secret key.
72 * This routine is used for example, by the kerberos server(s) with the
73 * key in question being the kerberos master key.
75 * Note: this routine calls mit_des_set_random_generator_seed.
79 mit_des_init_random_number_generator(key,p_seed)
81 mit_des_random_key_seed *p_seed;
83 mit_des_cblock seed; /* This must be 64 bits exactly */
86 krb5_int32 microseconds;
88 mit_des_cblock new_key;
90 krb5_address **addrs = 0;
94 * use a host id in generating the seed to ensure
95 * that different servers have different streams:
97 memset((char *)seed, 0, sizeof(seed));
98 if (!krb5_os_localaddr(&addrs) && addrs && *addrs) {
99 memcpy((char *)seed, (char *)addrs[0]->contents,
100 min(sizeof(seed), addrs[0]->length));
101 /* XXX may not do all of the seed. */
104 /* can't use krb5_free_addresses due to circular dependencies in
106 register krb5_address **addr2;
107 for (addr2 = addrs; *addr2; addr2++) {
108 krb5_xfree((*addr2)->contents);
114 * Generate a temporary value that depends on the key and host_id
115 * such that it gives no useful information about the key:
117 mit_des_set_random_generator_seed(key, p_seed);
118 mit_des_set_sequence_number(seed, p_seed);
119 mit_des_new_random_key(new_key, p_seed);
122 * use it to select a random stream:
124 mit_des_set_random_generator_seed(new_key, p_seed);
127 * use a time stamp to ensure that a server started later does not reuse
130 (void) krb5_us_timeofday(context, &timenow.seconds,
131 &timenow.microseconds); /* XXX return value */
132 mit_des_set_sequence_number((unsigned char *)&timenow, p_seed);
135 * use the time stamp finally to select the final seed using the
136 * current random number stream:
138 mit_des_new_random_key(new_key, p_seed);
139 mit_des_set_random_generator_seed(new_key, p_seed);
143 * This module implements a random number generator faculty such that the next
144 * number in any random number stream is very hard to predict without knowing
145 * the seed for that stream even given the preceeding random numbers.
149 * mit_des_set_random_generator_seed: this routine is used to select a random
150 * number stream. The stream that results is
151 * totally determined by the passed in key.
152 * (I.e., calling this routine again with the
153 * same key allows repeating a sequence of
156 * Requires: key is a valid des key. I.e., has correct parity and is not a
160 mit_des_set_random_generator_seed(key, p_seed)
162 mit_des_random_key_seed *p_seed;
166 /* select the new stream: (note errors are not possible here...) */
167 mit_des_key_sched(key, p_seed->random_sequence_key);
169 /* "seek" to the start of the stream: */
171 p_seed->sequence_number[i] = 0;
175 * mit_des_set_sequence_number: this routine is used to set the sequence number
176 * of the current random number stream. This routine
177 * may be used to "seek" within the current random
180 * Note that mit_des_set_random_generator_seed resets the sequence number to 0.
183 mit_des_set_sequence_number(new_sequence_number, p_seed)
184 mit_des_cblock new_sequence_number;
185 mit_des_random_key_seed *p_seed;
187 memcpy((char *)p_seed->sequence_number, (char *)new_sequence_number,
188 sizeof(p_seed->sequence_number));
192 * mit_des_generate_random_block: routine to return the next random number
193 * from the current random number stream.
194 * The returned number is 64 bits long.
196 * Requires: mit_des_set_random_generator_seed must have been called at least once
197 * before this routine is called.
200 mit_des_generate_random_block(block, p_seed)
201 mit_des_cblock block;
202 mit_des_random_key_seed *p_seed;
207 * Encrypt the sequence number to get the new random block:
209 mit_des_ecb_encrypt((unsigned long *)p_seed->sequence_number,
210 (unsigned long *)block,
211 p_seed->random_sequence_key, 1);
214 * Increment the sequence number as an 8 byte unsigned number with wrap:
217 for (i=0; i<8; i++) {
218 p_seed->sequence_number[i] = (p_seed->sequence_number[i] + 1) & 0xff;
219 if (p_seed->sequence_number[i])