libos-proto.h -> los-proto.h
[krb5.git] / src / lib / crypto / des / new_rn_key.c
1 /*
2  * $Source$
3  * $Author$
4  *
5  * Copyright 1988,1990 by the Massachusetts Institute of Technology.
6  * All Rights Reserved.
7  *
8  * For copying and distribution information, please see the file
9  * <krb5/copyright.h>.
10  *
11  * New pseudo-random key generator, using DES encryption to make the
12  * pseudo-random cycle as hard to break as DES.
13  *
14  * Written by Mark Lillibridge, MIT Project Athena
15  *
16  * Under U.S. law, this software may not be exported outside the US
17  * without license from the U.S. Commerce department.
18  */
19
20 #if !defined(lint) && !defined(SABER)
21 static char rcsid_new_rn_key_c[] =
22 "$Id$";
23 #endif  /* !lint & !SABER */
24
25 #include <krb5/krb5.h>
26 #include <krb5/ext-proto.h>
27 #include <krb5/los-proto.h>
28 #include "des_int.h"
29
30 #ifndef min
31 #define min(a,b) (((a) < (b)) ? (a) : (b))
32 #endif
33
34 /*
35  * mit_des_new_random_key: create a random des key
36  *
37  * Requires: mit_des_set_random_number_generater_seed must be at called least
38  *           once before this routine is called.
39  *
40  * Notes: the returned key has correct parity and is guarenteed not
41  *        to be a weak des key.  Mit_Des_generate_random_block is used to
42  *        provide the random bits.
43  */
44 int
45 mit_des_new_random_key(key, p_seed)
46     mit_des_cblock key;
47     mit_des_random_key_seed     *p_seed;
48 {
49     do {
50         mit_des_generate_random_block(key, p_seed);
51         mit_des_fixup_key_parity(key);
52     } while (mit_des_is_weak_key(key));
53
54     return(0);
55 }
56
57 /*
58  * mit_des_init_random_number_generator:
59  *
60  *    This routine takes a secret key possibly shared by a number
61  * of servers and uses it to generate a random number stream that is
62  * not shared by any of the other servers.  It does this by using the current
63  * process id, host id, and the current time to the nearest second.  The
64  * resulting stream seed is not useful information for cracking the secret
65  * key.   Moreover, this routine keeps no copy of the secret key.
66  * This routine is used for example, by the kerberos server(s) with the
67  * key in question being the kerberos master key.
68  *
69  * Note: this routine calls mit_des_set_random_generator_seed.
70  */
71
72 void mit_des_init_random_number_generator(key,p_seed)
73     mit_des_cblock key;
74     mit_des_random_key_seed     *p_seed;
75 {
76     mit_des_cblock seed; /* This must be 64 bits exactly */
77     struct tval {
78         krb5_int32 seconds;
79         krb5_int32 microseconds;
80     } timenow;
81     mit_des_cblock new_key;
82
83     krb5_address **addrs;
84
85     /*
86      * use a host id in generating the seed to ensure
87      * that different servers have different streams:
88      */
89     memset((char *)seed, 0, sizeof(seed));
90     if (!krb5_os_localaddr(&addrs) && *addrs) {
91         memcpy((char *)seed, (char *)addrs[0]->contents,
92               min(sizeof(seed), addrs[0]->length));
93         /* XXX may not do all of the seed. */
94     }
95     if (addrs) {
96         /* can't use krb5_free_address due to circular dependencies in
97            libraries */
98         register krb5_address **addr2;
99         for (addr2 = addrs; *addr2; addr2++) {
100             xfree((*addr2)->contents);
101             xfree(*addr2);
102         }
103         xfree(addrs);
104     }
105     /*
106      * Generate a tempory value that depends on the key and host_id
107      * such that it gives no useful information about the key:
108      */
109     mit_des_set_random_generator_seed(key, p_seed);
110     mit_des_set_sequence_number(seed, p_seed);
111     mit_des_new_random_key(new_key, p_seed);
112
113     /*
114      * use it to select a random stream:
115      */      
116     mit_des_set_random_generator_seed(new_key, p_seed);
117
118     /*
119      * use a time stamp to ensure that a server started later does not reuse
120      * an old stream:
121      */
122     (void) krb5_us_timeofday(&timenow.seconds,
123                              &timenow.microseconds); /* XXX return value */
124     mit_des_set_sequence_number((unsigned char *)&timenow, p_seed);
125
126     /*
127      * use the time stamp finally to select the final seed using the
128      * current random number stream:
129      */
130     mit_des_new_random_key(new_key, p_seed);
131     mit_des_set_random_generator_seed(new_key, p_seed);
132 }
133
134 /*
135  * This module implements a random number generator faculty such that the next
136  * number in any random number stream is very hard to predict without knowing
137  * the seed for that stream even given the preceeding random numbers.
138  */
139
140 /*
141  * mit_des_set_random_generator_seed: this routine is used to select a random
142  *                                number stream.  The stream that results is
143  *                                totally determined by the passed in key.
144  *                                (I.e., calling this routine again with the
145  *                                same key allows repeating a sequence of
146  *                                random numbers)
147  *
148  * Requires: key is a valid des key.  I.e., has correct parity and is not a
149  *           weak des key.
150  */
151 void
152 mit_des_set_random_generator_seed(key, p_seed)
153     mit_des_cblock key;
154     mit_des_random_key_seed     *p_seed;
155 {
156     register int i;
157
158     /* select the new stream: (note errors are not possible here...) */
159     mit_des_key_sched(key, p_seed->random_sequence_key);
160
161     /* "seek" to the start of the stream: */
162     for (i=0; i<8; i++)
163       p_seed->sequence_number[i] = 0;
164 }
165
166 /*
167  * mit_des_set_sequence_number: this routine is used to set the sequence number
168  *                          of the current random number stream.  This routine
169  *                          may be used to "seek" within the current random
170  *                          number stream.
171  *
172  * Note that mit_des_set_random_generator_seed resets the sequence number to 0.
173  */
174 void
175 mit_des_set_sequence_number(new_sequence_number, p_seed)
176     mit_des_cblock new_sequence_number;
177     mit_des_random_key_seed     *p_seed;
178 {
179     memcpy((char *)p_seed->sequence_number, (char *)new_sequence_number,
180           sizeof(p_seed->sequence_number));
181 }
182
183 /*
184  * mit_des_generate_random_block: routine to return the next random number
185  *                            from the current random number stream.
186  *                            The returned number is 64 bits long.
187  *
188  * Requires: mit_des_set_random_generator_seed must have been called at least once
189  *           before this routine is called.
190  */
191 void mit_des_generate_random_block(block, p_seed)
192     mit_des_cblock block;
193     mit_des_random_key_seed     *p_seed;
194 {
195     int i;
196
197     /*
198      * Encrypt the sequence number to get the new random block:
199      */
200     mit_des_ecb_encrypt((unsigned long *)p_seed->sequence_number, 
201                     (unsigned long *)block, 
202                     p_seed->random_sequence_key, 1);
203
204     /*
205      * Increment the sequence number as an 8 byte unsigned number with wrap:
206      * (using LSB here)
207      */
208     for (i=0; i<8; i++) {
209         p_seed->sequence_number[i] = (p_seed->sequence_number[i] + 1) & 0xff;
210         if (p_seed->sequence_number[i])
211           break;
212     }
213 }