Make pool and buffer sizes more sensible.
[u/mdw/catacomb] / rand.h
1 /* -*-c-*-
2 *
3 * $Id: rand.h,v 1.2 1999/10/12 21:00:15 mdw Exp $
4 *
5 * Secure random number generator
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
18 *
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Revision history --------------------------------------------------*
31 *
32 * $Log: rand.h,v $
33 * Revision 1.2 1999/10/12 21:00:15 mdw
34 * Make pool and buffer sizes more sensible.
35 *
36 * Revision 1.1 1999/09/03 08:41:12 mdw
37 * Initial import.
38 *
39 */
40
41 /*----- Notes on the random number generator ------------------------------*
42 *
43 * The algorithm is one of the author's own devising. It may therefore be
44 * worth a certain amount of skepticism. However, I've thought about this
45 * method for over a year before actually considering it worth implementing.
46 * With a little bit of luck, it should have received some peer review by the
47 * time this code is actually properly released, and it'll be worth a bit
48 * more confidence. My earlier generator was very similar in structure to
49 * the Linux /dev/random device. This generator is intended to address
50 * concerns I expressed about the Linux generator in a Usenet article to
51 * sci.crypt.
52 *
53 * The generator is divided into two parts: an input pool and an outpu
54 * buffer. New random data is placed into the pool in the way described
55 * below, which is shamelessly stolen from the Linux /dev/random generator.
56 * The only interaction that the pool has on the output buffer is through the
57 * keyed `gating' operation, which mixes up and redistributes all of the
58 * generator's state in an irreversible manner. Random bytes, when
59 * requested, are extracted from the output buffer in a linear fashion.
60 *
61 * The input pool is best seen as being eight shift registers in parallel.
62 * Data is added to the pool one octet at a time. Each bit of a new octet is
63 * added to a different shift register, by adding it (mod 2) with other bits
64 * according to the coefficients of a primitive polynomial. Each new byte is
65 * rotated before being added into the pool, in a half-hearted attempt to
66 * protect against biases in the input data (e.g., top bits being clear on
67 * ASCII text).
68 *
69 * The gating operation takes a keyed hash of the entire generator state,
70 * uses it as the key for a symmetric cipher, and encrypts the state. The
71 * key is then discarded. The result is that every ouptut bit of the
72 * operation depends in a complex way on every input bit, but the operation
73 * cannot be reversed.
74 *
75 * As an added wrinkle, 160 bits of the output buffer are never actually
76 * output. They are used in the gating operation only, as an extra item that
77 * an adversary has to guess before predicting generator output.
78 */
79
80 #ifndef RAND_H
81 #define RAND_H
82
83 #ifdef __cplusplus
84 extern "C" {
85 #endif
86
87 /*----- Header files ------------------------------------------------------*/
88
89 #include <stddef.h>
90
91 #include "rmd160-hmac.h"
92
93 /*----- Magic numbers -----------------------------------------------------*/
94
95 #define RAND_POOLSZ 128 /* Input pool size in bytes */
96 #define RAND_BUFSZ 128 /* Output buffer size in bytes */
97 #define RAND_SECSZ 20 /* Secret octets in output buffer */
98
99 #define RAND_IBITS (RAND_POOLSZ * 8)
100 #define RAND_OBITS (RAND_BUFSZ * 8)
101
102 /*----- Data structures ---------------------------------------------------*/
103
104 /* --- A random number generator pool --- */
105
106 typedef struct rand_pool {
107 octet pool[RAND_POOLSZ]; /* Actual contents of the pool */
108 unsigned i; /* Current index into pool */
109 unsigned irot; /* Current rotation applied */
110 unsigned ibits; /* Number of good bits in pool */
111 octet buf[RAND_BUFSZ]; /* Random octet output buffer */
112 unsigned o; /* Current index into buffer */
113 unsigned obits; /* Number of good bits in buffer */
114 rmd160_mackey k; /* Secret key for this pool */
115 const struct rand_source *s; /* System-specific noise source */
116 } rand_pool;
117
118 #define RAND_GLOBAL ((rand_pool *)0) /* The global randomness pool */
119
120 /* --- A noise source --- */
121
122 typedef struct rand_source {
123 void (*getnoise)(rand_pool */*r*/); /* Acquire more noise */
124 int (*timer)(rand_pool */*r*/); /* Get noise from current time */
125 } rand_source;
126
127 /*----- Functions provided ------------------------------------------------*/
128
129 /* --- @rand_init@ --- *
130 *
131 * Arguments: @rand_pool *r@ = pointer to a randomness pool
132 *
133 * Returns: ---
134 *
135 * Use: Initializes a randomness pool. The pool doesn't start out
136 * very random: that's your job to sort out.
137 */
138
139 extern void rand_init(rand_pool */*r*/);
140
141 /* --- @rand_noisesrc@ --- *
142 *
143 * Arguments: @rand_pool *r@ = pointer to a randomness pool
144 * @const rand_source *s@ = pointer to source definition
145 *
146 * Returns: ---
147 *
148 * Use: Sets a noise source for a randomness pool. When the pool's
149 * estimate of good random bits falls to zero, the @getnoise@
150 * function is called, passing the pool handle as an argument.
151 * It is expected to increase the number of good bits by at
152 * least one, because it'll be called over and over again until
153 * there are enough bits to satisfy the caller. The @timer@
154 * function is called frequently throughout the generator's
155 * operation.
156 */
157
158 extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/);
159
160 /* --- @rand_key@ --- *
161 *
162 * Arguments: @rand_pool *r@ = pointer to a randomness pool
163 * @const void *k@ = pointer to key data
164 * @size_t sz@ = size of key data
165 *
166 * Returns: ---
167 *
168 * Use: Sets the secret key for a randomness pool. The key is used
169 * when mixing in new random bits.
170 */
171
172 extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/);
173
174 /* --- @rand_add@ --- *
175 *
176 * Arguments: @rand_pool *r@ = pointer to a randomness pool
177 * @const void *p@ = pointer a buffer of data to add
178 * @size_t sz@ = size of the data buffer
179 * @unsigned goodbits@ = number of good bits estimated in buffer
180 *
181 * Returns: ---
182 *
183 * Use: Mixes the data in the buffer with the contents of the
184 * pool. The estimate of the number of good bits is added to
185 * the pool's own count. The mixing operation is not
186 * cryptographically strong. However, data in the input pool
187 * isn't output directly, only through the one-way gating
188 * operation, so that shouldn't matter.
189 */
190
191 extern void rand_add(rand_pool */*r*/,
192 const void */*p*/, size_t /*sz*/,
193 unsigned /*goodbits*/);
194
195 /* --- @rand_goodbits@ --- *
196 *
197 * Arguments: @rand_pool *r@ = pointer to a randomness pool
198 *
199 * Returns: Estimate of the number of good bits remaining in the pool.
200 */
201
202 extern unsigned rand_goodbits(rand_pool */*r*/);
203
204 /* --- @rand_gate@ --- *
205 *
206 * Arguments: @rand_pool *r@ = pointer to a randomness pool
207 *
208 * Returns: ---
209 *
210 * Use: Mixes up the entire state of the generator in a nonreversible
211 * way.
212 */
213
214 extern void rand_gate(rand_pool */*r*/);
215
216 /* --- @rand_stretch@ --- *
217 *
218 * Arguments: @rand_pool *r@ = pointer to a randomness pool
219 *
220 * Returns: ---
221 *
222 * Use: Stretches the contents of the output buffer by transforming
223 * it in a nonreversible way. This doesn't add any entropy
224 * worth speaking about, but it works well enough when the
225 * caller doesn't care about that sort of thing.
226 */
227
228 extern void rand_stretch(rand_pool */*r*/);
229
230 /* --- @rand_get@ --- *
231 *
232 * Arguments: @rand_pool *r@ = pointer to a randomness pool
233 * @void *p@ = pointer to output buffer
234 * @size_t sz@ = size of output buffer
235 *
236 * Returns: ---
237 *
238 * Use: Gets random data from the pool. The pool's contents can't be
239 * determined from the output of this function; nor can the
240 * output data be determined from a knowledge of the data input
241 * to the pool wihtout also having knowledge of the secret key.
242 * The good bits counter is decremented, although no special
243 * action is taken if it reaches zero.
244 */
245
246 extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
247
248 /* --- @rand_getgood@ --- *
249 *
250 * Arguments: @rand_pool *r@ = pointer to a randomness pool
251 * @void *p@ = pointer to output buffer
252 * @size_t sz@ = size of output buffer
253 *
254 * Returns: ---
255 *
256 * Use: Gets random data from the pool. The pool's contents can't be
257 * determined from the output of this function; nor can the
258 * output data be determined from a knowledge of the data input
259 * to the pool wihtout also having knowledge of the secret key.
260 * If a noise source is attached to the pool in question, it is
261 * called to replenish the supply of good bits in the pool;
262 * otherwise this call is equivalent to @rand_get@.
263 */
264
265 extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
266
267 /*----- That's all, folks -------------------------------------------------*/
268
269 #ifdef __cplusplus
270 }
271 #endif
272
273 #endif