1*10465441SEvalZero /*
2*10465441SEvalZero * magic.c - PPP Magic Number routines.
3*10465441SEvalZero *
4*10465441SEvalZero * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
5*10465441SEvalZero *
6*10465441SEvalZero * Redistribution and use in source and binary forms, with or without
7*10465441SEvalZero * modification, are permitted provided that the following conditions
8*10465441SEvalZero * are met:
9*10465441SEvalZero *
10*10465441SEvalZero * 1. Redistributions of source code must retain the above copyright
11*10465441SEvalZero * notice, this list of conditions and the following disclaimer.
12*10465441SEvalZero *
13*10465441SEvalZero * 2. Redistributions in binary form must reproduce the above copyright
14*10465441SEvalZero * notice, this list of conditions and the following disclaimer in
15*10465441SEvalZero * the documentation and/or other materials provided with the
16*10465441SEvalZero * distribution.
17*10465441SEvalZero *
18*10465441SEvalZero * 3. The name "Carnegie Mellon University" must not be used to
19*10465441SEvalZero * endorse or promote products derived from this software without
20*10465441SEvalZero * prior written permission. For permission or any legal
21*10465441SEvalZero * details, please contact
22*10465441SEvalZero * Office of Technology Transfer
23*10465441SEvalZero * Carnegie Mellon University
24*10465441SEvalZero * 5000 Forbes Avenue
25*10465441SEvalZero * Pittsburgh, PA 15213-3890
26*10465441SEvalZero * (412) 268-4387, fax: (412) 268-7395
27*10465441SEvalZero * [email protected]
28*10465441SEvalZero *
29*10465441SEvalZero * 4. Redistributions of any form whatsoever must retain the following
30*10465441SEvalZero * acknowledgment:
31*10465441SEvalZero * "This product includes software developed by Computing Services
32*10465441SEvalZero * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
33*10465441SEvalZero *
34*10465441SEvalZero * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
35*10465441SEvalZero * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
36*10465441SEvalZero * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
37*10465441SEvalZero * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
38*10465441SEvalZero * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
39*10465441SEvalZero * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
40*10465441SEvalZero * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
41*10465441SEvalZero */
42*10465441SEvalZero /*****************************************************************************
43*10465441SEvalZero * randm.c - Random number generator program file.
44*10465441SEvalZero *
45*10465441SEvalZero * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
46*10465441SEvalZero * Copyright (c) 1998 by Global Election Systems Inc.
47*10465441SEvalZero *
48*10465441SEvalZero * The authors hereby grant permission to use, copy, modify, distribute,
49*10465441SEvalZero * and license this software and its documentation for any purpose, provided
50*10465441SEvalZero * that existing copyright notices are retained in all copies and that this
51*10465441SEvalZero * notice and the following disclaimer are included verbatim in any
52*10465441SEvalZero * distributions. No written agreement, license, or royalty fee is required
53*10465441SEvalZero * for any of the authorized uses.
54*10465441SEvalZero *
55*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
56*10465441SEvalZero * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
57*10465441SEvalZero * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
58*10465441SEvalZero * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
59*10465441SEvalZero * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
60*10465441SEvalZero * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
61*10465441SEvalZero * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
62*10465441SEvalZero * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
63*10465441SEvalZero * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
64*10465441SEvalZero * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65*10465441SEvalZero *
66*10465441SEvalZero ******************************************************************************
67*10465441SEvalZero * REVISION HISTORY
68*10465441SEvalZero *
69*10465441SEvalZero * 03-01-01 Marc Boucher <[email protected]>
70*10465441SEvalZero * Ported to lwIP.
71*10465441SEvalZero * 98-06-03 Guy Lancaster <[email protected]>, Global Election Systems Inc.
72*10465441SEvalZero * Extracted from avos.
73*10465441SEvalZero *****************************************************************************/
74*10465441SEvalZero
75*10465441SEvalZero #include "netif/ppp/ppp_opts.h"
76*10465441SEvalZero #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
77*10465441SEvalZero
78*10465441SEvalZero #include "netif/ppp/ppp_impl.h"
79*10465441SEvalZero #include "netif/ppp/magic.h"
80*10465441SEvalZero
81*10465441SEvalZero #if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */
82*10465441SEvalZero
83*10465441SEvalZero #include "netif/ppp/pppcrypt.h"
84*10465441SEvalZero
85*10465441SEvalZero #define MD5_HASH_SIZE 16
86*10465441SEvalZero static char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */
87*10465441SEvalZero static long magic_randcount; /* Pseudo-random incrementer */
88*10465441SEvalZero static u32_t magic_randomseed; /* Seed used for random number generation. */
89*10465441SEvalZero
90*10465441SEvalZero /*
91*10465441SEvalZero * Churn the randomness pool on a random event. Call this early and often
92*10465441SEvalZero * on random and semi-random system events to build randomness in time for
93*10465441SEvalZero * usage. For randomly timed events, pass a null pointer and a zero length
94*10465441SEvalZero * and this will use the system timer and other sources to add randomness.
95*10465441SEvalZero * If new random data is available, pass a pointer to that and it will be
96*10465441SEvalZero * included.
97*10465441SEvalZero *
98*10465441SEvalZero * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
99*10465441SEvalZero */
magic_churnrand(char * rand_data,u32_t rand_len)100*10465441SEvalZero static void magic_churnrand(char *rand_data, u32_t rand_len) {
101*10465441SEvalZero lwip_md5_context md5_ctx;
102*10465441SEvalZero
103*10465441SEvalZero /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */
104*10465441SEvalZero lwip_md5_init(&md5_ctx);
105*10465441SEvalZero lwip_md5_starts(&md5_ctx);
106*10465441SEvalZero lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool));
107*10465441SEvalZero if (rand_data) {
108*10465441SEvalZero lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len);
109*10465441SEvalZero } else {
110*10465441SEvalZero struct {
111*10465441SEvalZero /* INCLUDE fields for any system sources of randomness */
112*10465441SEvalZero u32_t jiffies;
113*10465441SEvalZero #ifdef LWIP_RAND
114*10465441SEvalZero u32_t rand;
115*10465441SEvalZero #endif /* LWIP_RAND */
116*10465441SEvalZero } sys_data;
117*10465441SEvalZero magic_randomseed += sys_jiffies();
118*10465441SEvalZero sys_data.jiffies = magic_randomseed;
119*10465441SEvalZero #ifdef LWIP_RAND
120*10465441SEvalZero sys_data.rand = LWIP_RAND();
121*10465441SEvalZero #endif /* LWIP_RAND */
122*10465441SEvalZero /* Load sys_data fields here. */
123*10465441SEvalZero lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data));
124*10465441SEvalZero }
125*10465441SEvalZero lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool);
126*10465441SEvalZero lwip_md5_free(&md5_ctx);
127*10465441SEvalZero /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */
128*10465441SEvalZero }
129*10465441SEvalZero
130*10465441SEvalZero /*
131*10465441SEvalZero * Initialize the random number generator.
132*10465441SEvalZero */
magic_init(void)133*10465441SEvalZero void magic_init(void) {
134*10465441SEvalZero magic_churnrand(NULL, 0);
135*10465441SEvalZero }
136*10465441SEvalZero
137*10465441SEvalZero /*
138*10465441SEvalZero * Randomize our random seed value.
139*10465441SEvalZero */
magic_randomize(void)140*10465441SEvalZero void magic_randomize(void) {
141*10465441SEvalZero magic_churnrand(NULL, 0);
142*10465441SEvalZero }
143*10465441SEvalZero
144*10465441SEvalZero /*
145*10465441SEvalZero * magic_random_bytes - Fill a buffer with random bytes.
146*10465441SEvalZero *
147*10465441SEvalZero * Use the random pool to generate random data. This degrades to pseudo
148*10465441SEvalZero * random when used faster than randomness is supplied using magic_churnrand().
149*10465441SEvalZero * Note: It's important that there be sufficient randomness in magic_randpool
150*10465441SEvalZero * before this is called for otherwise the range of the result may be
151*10465441SEvalZero * narrow enough to make a search feasible.
152*10465441SEvalZero *
153*10465441SEvalZero * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
154*10465441SEvalZero *
155*10465441SEvalZero * XXX Why does he not just call magic_churnrand() for each block? Probably
156*10465441SEvalZero * so that you don't ever publish the seed which could possibly help
157*10465441SEvalZero * predict future values.
158*10465441SEvalZero * XXX Why don't we preserve md5 between blocks and just update it with
159*10465441SEvalZero * magic_randcount each time? Probably there is a weakness but I wish that
160*10465441SEvalZero * it was documented.
161*10465441SEvalZero */
magic_random_bytes(unsigned char * buf,u32_t buf_len)162*10465441SEvalZero void magic_random_bytes(unsigned char *buf, u32_t buf_len) {
163*10465441SEvalZero lwip_md5_context md5_ctx;
164*10465441SEvalZero u_char tmp[MD5_HASH_SIZE];
165*10465441SEvalZero u32_t n;
166*10465441SEvalZero
167*10465441SEvalZero while (buf_len > 0) {
168*10465441SEvalZero lwip_md5_init(&md5_ctx);
169*10465441SEvalZero lwip_md5_starts(&md5_ctx);
170*10465441SEvalZero lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool));
171*10465441SEvalZero lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount));
172*10465441SEvalZero lwip_md5_finish(&md5_ctx, tmp);
173*10465441SEvalZero lwip_md5_free(&md5_ctx);
174*10465441SEvalZero magic_randcount++;
175*10465441SEvalZero n = LWIP_MIN(buf_len, MD5_HASH_SIZE);
176*10465441SEvalZero MEMCPY(buf, tmp, n);
177*10465441SEvalZero buf += n;
178*10465441SEvalZero buf_len -= n;
179*10465441SEvalZero }
180*10465441SEvalZero }
181*10465441SEvalZero
182*10465441SEvalZero /*
183*10465441SEvalZero * Return a new random number.
184*10465441SEvalZero */
magic(void)185*10465441SEvalZero u32_t magic(void) {
186*10465441SEvalZero u32_t new_rand;
187*10465441SEvalZero
188*10465441SEvalZero magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand));
189*10465441SEvalZero
190*10465441SEvalZero return new_rand;
191*10465441SEvalZero }
192*10465441SEvalZero
193*10465441SEvalZero #else /* PPP_MD5_RANDM */
194*10465441SEvalZero
195*10465441SEvalZero /*****************************/
196*10465441SEvalZero /*** LOCAL DATA STRUCTURES ***/
197*10465441SEvalZero /*****************************/
198*10465441SEvalZero #ifndef LWIP_RAND
199*10465441SEvalZero static int magic_randomized; /* Set when truely randomized. */
200*10465441SEvalZero #endif /* LWIP_RAND */
201*10465441SEvalZero static u32_t magic_randomseed; /* Seed used for random number generation. */
202*10465441SEvalZero
203*10465441SEvalZero
204*10465441SEvalZero /***********************************/
205*10465441SEvalZero /*** PUBLIC FUNCTION DEFINITIONS ***/
206*10465441SEvalZero /***********************************/
207*10465441SEvalZero
208*10465441SEvalZero /*
209*10465441SEvalZero * Initialize the random number generator.
210*10465441SEvalZero *
211*10465441SEvalZero * Here we attempt to compute a random number seed but even if
212*10465441SEvalZero * it isn't random, we'll randomize it later.
213*10465441SEvalZero *
214*10465441SEvalZero * The current method uses the fields from the real time clock,
215*10465441SEvalZero * the idle process counter, the millisecond counter, and the
216*10465441SEvalZero * hardware timer tick counter. When this is invoked
217*10465441SEvalZero * in startup(), then the idle counter and timer values may
218*10465441SEvalZero * repeat after each boot and the real time clock may not be
219*10465441SEvalZero * operational. Thus we call it again on the first random
220*10465441SEvalZero * event.
221*10465441SEvalZero */
magic_init(void)222*10465441SEvalZero void magic_init(void) {
223*10465441SEvalZero magic_randomseed += sys_jiffies();
224*10465441SEvalZero #ifndef LWIP_RAND
225*10465441SEvalZero /* Initialize the Borland random number generator. */
226*10465441SEvalZero srand((unsigned)magic_randomseed);
227*10465441SEvalZero #endif /* LWIP_RAND */
228*10465441SEvalZero }
229*10465441SEvalZero
230*10465441SEvalZero /*
231*10465441SEvalZero * magic_init - Initialize the magic number generator.
232*10465441SEvalZero *
233*10465441SEvalZero * Randomize our random seed value. Here we use the fact that
234*10465441SEvalZero * this function is called at *truely random* times by the polling
235*10465441SEvalZero * and network functions. Here we only get 16 bits of new random
236*10465441SEvalZero * value but we use the previous value to randomize the other 16
237*10465441SEvalZero * bits.
238*10465441SEvalZero */
magic_randomize(void)239*10465441SEvalZero void magic_randomize(void) {
240*10465441SEvalZero #ifndef LWIP_RAND
241*10465441SEvalZero if (!magic_randomized) {
242*10465441SEvalZero magic_randomized = !0;
243*10465441SEvalZero magic_init();
244*10465441SEvalZero /* The initialization function also updates the seed. */
245*10465441SEvalZero } else {
246*10465441SEvalZero #endif /* LWIP_RAND */
247*10465441SEvalZero magic_randomseed += sys_jiffies();
248*10465441SEvalZero #ifndef LWIP_RAND
249*10465441SEvalZero }
250*10465441SEvalZero #endif /* LWIP_RAND */
251*10465441SEvalZero }
252*10465441SEvalZero
253*10465441SEvalZero /*
254*10465441SEvalZero * Return a new random number.
255*10465441SEvalZero *
256*10465441SEvalZero * Here we use the Borland rand() function to supply a pseudo random
257*10465441SEvalZero * number which we make truely random by combining it with our own
258*10465441SEvalZero * seed which is randomized by truely random events.
259*10465441SEvalZero * Thus the numbers will be truely random unless there have been no
260*10465441SEvalZero * operator or network events in which case it will be pseudo random
261*10465441SEvalZero * seeded by the real time clock.
262*10465441SEvalZero */
magic(void)263*10465441SEvalZero u32_t magic(void) {
264*10465441SEvalZero #ifdef LWIP_RAND
265*10465441SEvalZero return LWIP_RAND() + magic_randomseed;
266*10465441SEvalZero #else /* LWIP_RAND */
267*10465441SEvalZero return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed;
268*10465441SEvalZero #endif /* LWIP_RAND */
269*10465441SEvalZero }
270*10465441SEvalZero
271*10465441SEvalZero /*
272*10465441SEvalZero * magic_random_bytes - Fill a buffer with random bytes.
273*10465441SEvalZero */
magic_random_bytes(unsigned char * buf,u32_t buf_len)274*10465441SEvalZero void magic_random_bytes(unsigned char *buf, u32_t buf_len) {
275*10465441SEvalZero u32_t new_rand, n;
276*10465441SEvalZero
277*10465441SEvalZero while (buf_len > 0) {
278*10465441SEvalZero new_rand = magic();
279*10465441SEvalZero n = LWIP_MIN(buf_len, sizeof(new_rand));
280*10465441SEvalZero MEMCPY(buf, &new_rand, n);
281*10465441SEvalZero buf += n;
282*10465441SEvalZero buf_len -= n;
283*10465441SEvalZero }
284*10465441SEvalZero }
285*10465441SEvalZero #endif /* PPP_MD5_RANDM */
286*10465441SEvalZero
287*10465441SEvalZero /*
288*10465441SEvalZero * Return a new random number between 0 and (2^pow)-1 included.
289*10465441SEvalZero */
magic_pow(u8_t pow)290*10465441SEvalZero u32_t magic_pow(u8_t pow) {
291*10465441SEvalZero return magic() & ~(~0UL<<pow);
292*10465441SEvalZero }
293*10465441SEvalZero
294*10465441SEvalZero #endif /* PPP_SUPPORT */
295