Major memory management overhaul. Added arena support. Use the secure
[u/mdw/catacomb] / rand.h
1 /* -*-c-*-
2 *
3 * $Id: rand.h,v 1.5 1999/12/13 15:34: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.5 1999/12/13 15:34:15 mdw
34 * Fix a typo.
35 *
36 * Revision 1.4 1999/12/10 23:29:48 mdw
37 * Change header file guard names.
38 *
39 * Revision 1.3 1999/10/15 21:04:30 mdw
40 * Increase output buffer a bit for performance.
41 *
42 * Revision 1.2 1999/10/12 21:00:15 mdw
43 * Make pool and buffer sizes more sensible.
44 *
45 * Revision 1.1 1999/09/03 08:41:12 mdw
46 * Initial import.
47 *
48 */
49
50 /*----- Notes on the random number generator ------------------------------*
51 *
52 * The algorithm is one of the author's own devising. It may therefore be
53 * worth a certain amount of skepticism. However, I've thought about this
54 * method for over a year before actually considering it worth implementing.
55 * With a little bit of luck, it should have received some peer review by the
56 * time this code is actually properly released, and it'll be worth a bit
57 * more confidence. My earlier generator was very similar in structure to
58 * the Linux /dev/random device. This generator is intended to address
59 * concerns I expressed about the Linux generator in a Usenet article to
60 * sci.crypt.
61 *
62 * The generator is divided into two parts: an input pool and an output
63 * buffer. New random data is placed into the pool in the way described
64 * below, which is shamelessly stolen from the Linux /dev/random generator.
65 * The only interaction that the pool has on the output buffer is through the
66 * keyed `gating' operation, which mixes up and redistributes all of the
67 * generator's state in an irreversible manner. Random bytes, when
68 * requested, are extracted from the output buffer in a linear fashion.
69 *
70 * The input pool is best seen as being eight shift registers in parallel.
71 * Data is added to the pool one octet at a time. Each bit of a new octet is
72 * added to a different shift register, by adding it (mod 2) with other bits
73 * according to the coefficients of a primitive polynomial. Each new byte is
74 * rotated before being added into the pool, in a half-hearted attempt to
75 * protect against biases in the input data (e.g., top bits being clear on
76 * ASCII text).
77 *
78 * The gating operation takes a keyed hash of the entire generator state,
79 * uses it as the key for a symmetric cipher, and encrypts the state. The
80 * key is then discarded. The result is that every ouptut bit of the
81 * operation depends in a complex way on every input bit, but the operation
82 * cannot be reversed.
83 *
84 * As an added wrinkle, 160 bits of the output buffer are never actually
85 * output. They are used in the gating operation only, as an extra item that
86 * an adversary has to guess before predicting generator output.
87 */
88
89 #ifndef CATACOMB_RAND_H
90 #define CATACOMB_RAND_H
91
92 #ifdef __cplusplus
93 extern "C" {
94 #endif
95
96 /*----- Header files ------------------------------------------------------*/
97
98 #include <stddef.h>
99
100 #ifndef CATACOMB_GRAND_H
101 # include "grand.h"
102 #endif
103
104 #ifndef CATACOMB_RMD160_HMAC_H
105 # include "rmd160-hmac.h"
106 #endif
107
108 /*----- Magic numbers -----------------------------------------------------*/
109
110 #define RAND_POOLSZ 128 /* Input pool size in bytes */
111 #define RAND_BUFSZ 512 /* Output buffer size in bytes */
112 #define RAND_SECSZ 20 /* Secret octets in output buffer */
113
114 #define RAND_IBITS (RAND_POOLSZ * 8)
115 #define RAND_OBITS (RAND_BUFSZ * 8)
116
117 /*----- Data structures ---------------------------------------------------*/
118
119 /* --- A random number generator pool --- */
120
121 typedef struct rand_pool {
122 octet pool[RAND_POOLSZ]; /* Actual contents of the pool */
123 unsigned i; /* Current index into pool */
124 unsigned irot; /* Current rotation applied */
125 unsigned ibits; /* Number of good bits in pool */
126 octet buf[RAND_BUFSZ]; /* Random octet output buffer */
127 unsigned o; /* Current index into buffer */
128 unsigned obits; /* Number of good bits in buffer */
129 rmd160_mackey k; /* Secret key for this pool */
130 const struct rand_source *s; /* System-specific noise source */
131 } rand_pool;
132
133 #define RAND_GLOBAL ((rand_pool *)0) /* The global randomness pool */
134
135 /* --- A noise source --- */
136
137 typedef struct rand_source {
138 void (*getnoise)(rand_pool */*r*/); /* Acquire more noise */
139 int (*timer)(rand_pool */*r*/); /* Get noise from current time */
140 } rand_source;
141
142 /*----- Functions provided ------------------------------------------------*/
143
144 /* --- @rand_init@ --- *
145 *
146 * Arguments: @rand_pool *r@ = pointer to a randomness pool
147 *
148 * Returns: ---
149 *
150 * Use: Initializes a randomness pool. The pool doesn't start out
151 * very random: that's your job to sort out.
152 */
153
154 extern void rand_init(rand_pool */*r*/);
155
156 /* --- @rand_noisesrc@ --- *
157 *
158 * Arguments: @rand_pool *r@ = pointer to a randomness pool
159 * @const rand_source *s@ = pointer to source definition
160 *
161 * Returns: ---
162 *
163 * Use: Sets a noise source for a randomness pool. When the pool's
164 * estimate of good random bits falls to zero, the @getnoise@
165 * function is called, passing the pool handle as an argument.
166 * It is expected to increase the number of good bits by at
167 * least one, because it'll be called over and over again until
168 * there are enough bits to satisfy the caller. The @timer@
169 * function is called frequently throughout the generator's
170 * operation.
171 */
172
173 extern void rand_noisesrc(rand_pool */*r*/, const rand_source */*s*/);
174
175 /* --- @rand_key@ --- *
176 *
177 * Arguments: @rand_pool *r@ = pointer to a randomness pool
178 * @const void *k@ = pointer to key data
179 * @size_t sz@ = size of key data
180 *
181 * Returns: ---
182 *
183 * Use: Sets the secret key for a randomness pool. The key is used
184 * when mixing in new random bits.
185 */
186
187 extern void rand_key(rand_pool */*r*/, const void */*k*/, size_t /*sz*/);
188
189 /* --- @rand_add@ --- *
190 *
191 * Arguments: @rand_pool *r@ = pointer to a randomness pool
192 * @const void *p@ = pointer a buffer of data to add
193 * @size_t sz@ = size of the data buffer
194 * @unsigned goodbits@ = number of good bits estimated in buffer
195 *
196 * Returns: ---
197 *
198 * Use: Mixes the data in the buffer with the contents of the
199 * pool. The estimate of the number of good bits is added to
200 * the pool's own count. The mixing operation is not
201 * cryptographically strong. However, data in the input pool
202 * isn't output directly, only through the one-way gating
203 * operation, so that shouldn't matter.
204 */
205
206 extern void rand_add(rand_pool */*r*/,
207 const void */*p*/, size_t /*sz*/,
208 unsigned /*goodbits*/);
209
210 /* --- @rand_goodbits@ --- *
211 *
212 * Arguments: @rand_pool *r@ = pointer to a randomness pool
213 *
214 * Returns: Estimate of the number of good bits remaining in the pool.
215 */
216
217 extern unsigned rand_goodbits(rand_pool */*r*/);
218
219 /* --- @rand_gate@ --- *
220 *
221 * Arguments: @rand_pool *r@ = pointer to a randomness pool
222 *
223 * Returns: ---
224 *
225 * Use: Mixes up the entire state of the generator in a nonreversible
226 * way.
227 */
228
229 extern void rand_gate(rand_pool */*r*/);
230
231 /* --- @rand_stretch@ --- *
232 *
233 * Arguments: @rand_pool *r@ = pointer to a randomness pool
234 *
235 * Returns: ---
236 *
237 * Use: Stretches the contents of the output buffer by transforming
238 * it in a nonreversible way. This doesn't add any entropy
239 * worth speaking about, but it works well enough when the
240 * caller doesn't care about that sort of thing.
241 */
242
243 extern void rand_stretch(rand_pool */*r*/);
244
245 /* --- @rand_get@ --- *
246 *
247 * Arguments: @rand_pool *r@ = pointer to a randomness pool
248 * @void *p@ = pointer to output buffer
249 * @size_t sz@ = size of output buffer
250 *
251 * Returns: ---
252 *
253 * Use: Gets random data from the pool. The pool's contents can't be
254 * determined from the output of this function; nor can the
255 * output data be determined from a knowledge of the data input
256 * to the pool without also having knowledge of the secret key.
257 * The good bits counter is decremented, although no special
258 * action is taken if it reaches zero.
259 */
260
261 extern void rand_get(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
262
263 /* --- @rand_getgood@ --- *
264 *
265 * Arguments: @rand_pool *r@ = pointer to a randomness pool
266 * @void *p@ = pointer to output buffer
267 * @size_t sz@ = size of output buffer
268 *
269 * Returns: ---
270 *
271 * Use: Gets random data from the pool. The pool's contents can't be
272 * determined from the output of this function; nor can the
273 * output data be determined from a knowledge of the data input
274 * to the pool wihtout also having knowledge of the secret key.
275 * If a noise source is attached to the pool in question, it is
276 * called to replenish the supply of good bits in the pool;
277 * otherwise this call is equivalent to @rand_get@.
278 */
279
280 extern void rand_getgood(rand_pool */*r*/, void */*p*/, size_t /*sz*/);
281
282 /*----- Generic random number generator interface -------------------------*/
283
284 /* --- Miscellaneous operations --- */
285
286 enum {
287 RAND_GATE = GRAND_SPECIFIC, /* No args */
288 RAND_STRETCH, /* No args */
289 RAND_KEY, /* @const void *k, size_t sz@ */
290 RAND_NOISESRC /* @const rand_source *s@ */
291 };
292
293 /* --- Default random number generator --- */
294
295 extern grand rand_global;
296
297 /* --- @rand_create@ --- *
298 *
299 * Arguments: ---
300 *
301 * Returns: Pointer to a generic generator.
302 *
303 * Use: Constructs a generic generator interface over a Catacomb
304 * entropy pool generator.
305 */
306
307 extern grand *rand_create(void);
308
309 /*----- That's all, folks -------------------------------------------------*/
310
311 #ifdef __cplusplus
312 }
313 #endif
314
315 #endif