1195972f6Sopenharmony_ci/* 2195972f6Sopenharmony_ci * magic.c - PPP Magic Number routines. 3195972f6Sopenharmony_ci * 4195972f6Sopenharmony_ci * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 5195972f6Sopenharmony_ci * 6195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 7195972f6Sopenharmony_ci * modification, are permitted provided that the following conditions 8195972f6Sopenharmony_ci * are met: 9195972f6Sopenharmony_ci * 10195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 11195972f6Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 12195972f6Sopenharmony_ci * 13195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 14195972f6Sopenharmony_ci * notice, this list of conditions and the following disclaimer in 15195972f6Sopenharmony_ci * the documentation and/or other materials provided with the 16195972f6Sopenharmony_ci * distribution. 17195972f6Sopenharmony_ci * 18195972f6Sopenharmony_ci * 3. The name "Carnegie Mellon University" must not be used to 19195972f6Sopenharmony_ci * endorse or promote products derived from this software without 20195972f6Sopenharmony_ci * prior written permission. For permission or any legal 21195972f6Sopenharmony_ci * details, please contact 22195972f6Sopenharmony_ci * Office of Technology Transfer 23195972f6Sopenharmony_ci * Carnegie Mellon University 24195972f6Sopenharmony_ci * 5000 Forbes Avenue 25195972f6Sopenharmony_ci * Pittsburgh, PA 15213-3890 26195972f6Sopenharmony_ci * (412) 268-4387, fax: (412) 268-7395 27195972f6Sopenharmony_ci * tech-transfer@andrew.cmu.edu 28195972f6Sopenharmony_ci * 29195972f6Sopenharmony_ci * 4. Redistributions of any form whatsoever must retain the following 30195972f6Sopenharmony_ci * acknowledgment: 31195972f6Sopenharmony_ci * "This product includes software developed by Computing Services 32195972f6Sopenharmony_ci * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 33195972f6Sopenharmony_ci * 34195972f6Sopenharmony_ci * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 35195972f6Sopenharmony_ci * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 36195972f6Sopenharmony_ci * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 37195972f6Sopenharmony_ci * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38195972f6Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 39195972f6Sopenharmony_ci * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 40195972f6Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41195972f6Sopenharmony_ci */ 42195972f6Sopenharmony_ci/***************************************************************************** 43195972f6Sopenharmony_ci* randm.c - Random number generator program file. 44195972f6Sopenharmony_ci* 45195972f6Sopenharmony_ci* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 46195972f6Sopenharmony_ci* Copyright (c) 1998 by Global Election Systems Inc. 47195972f6Sopenharmony_ci* 48195972f6Sopenharmony_ci* The authors hereby grant permission to use, copy, modify, distribute, 49195972f6Sopenharmony_ci* and license this software and its documentation for any purpose, provided 50195972f6Sopenharmony_ci* that existing copyright notices are retained in all copies and that this 51195972f6Sopenharmony_ci* notice and the following disclaimer are included verbatim in any 52195972f6Sopenharmony_ci* distributions. No written agreement, license, or royalty fee is required 53195972f6Sopenharmony_ci* for any of the authorized uses. 54195972f6Sopenharmony_ci* 55195972f6Sopenharmony_ci* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 56195972f6Sopenharmony_ci* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 57195972f6Sopenharmony_ci* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 58195972f6Sopenharmony_ci* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 59195972f6Sopenharmony_ci* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 60195972f6Sopenharmony_ci* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 61195972f6Sopenharmony_ci* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 62195972f6Sopenharmony_ci* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 63195972f6Sopenharmony_ci* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 64195972f6Sopenharmony_ci* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65195972f6Sopenharmony_ci* 66195972f6Sopenharmony_ci****************************************************************************** 67195972f6Sopenharmony_ci* REVISION HISTORY 68195972f6Sopenharmony_ci* 69195972f6Sopenharmony_ci* 03-01-01 Marc Boucher <marc@mbsi.ca> 70195972f6Sopenharmony_ci* Ported to lwIP. 71195972f6Sopenharmony_ci* 98-06-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 72195972f6Sopenharmony_ci* Extracted from avos. 73195972f6Sopenharmony_ci*****************************************************************************/ 74195972f6Sopenharmony_ci 75195972f6Sopenharmony_ci#include "netif/ppp/ppp_opts.h" 76195972f6Sopenharmony_ci#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 77195972f6Sopenharmony_ci 78195972f6Sopenharmony_ci#include "netif/ppp/ppp_impl.h" 79195972f6Sopenharmony_ci#include "netif/ppp/magic.h" 80195972f6Sopenharmony_ci 81195972f6Sopenharmony_ci#if PPP_MD5_RANDM /* Using MD5 for better randomness if enabled */ 82195972f6Sopenharmony_ci 83195972f6Sopenharmony_ci#include "netif/ppp/pppcrypt.h" 84195972f6Sopenharmony_ci 85195972f6Sopenharmony_ci#define MD5_HASH_SIZE 16 86195972f6Sopenharmony_cistatic char magic_randpool[MD5_HASH_SIZE]; /* Pool of randomness. */ 87195972f6Sopenharmony_cistatic long magic_randcount; /* Pseudo-random incrementer */ 88195972f6Sopenharmony_cistatic u32_t magic_randomseed; /* Seed used for random number generation. */ 89195972f6Sopenharmony_ci 90195972f6Sopenharmony_ci/* 91195972f6Sopenharmony_ci * Churn the randomness pool on a random event. Call this early and often 92195972f6Sopenharmony_ci * on random and semi-random system events to build randomness in time for 93195972f6Sopenharmony_ci * usage. For randomly timed events, pass a null pointer and a zero length 94195972f6Sopenharmony_ci * and this will use the system timer and other sources to add randomness. 95195972f6Sopenharmony_ci * If new random data is available, pass a pointer to that and it will be 96195972f6Sopenharmony_ci * included. 97195972f6Sopenharmony_ci * 98195972f6Sopenharmony_ci * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 99195972f6Sopenharmony_ci */ 100195972f6Sopenharmony_cistatic void magic_churnrand(char *rand_data, u32_t rand_len) { 101195972f6Sopenharmony_ci lwip_md5_context md5_ctx; 102195972f6Sopenharmony_ci 103195972f6Sopenharmony_ci /* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: %u@%P\n", rand_len, rand_data)); */ 104195972f6Sopenharmony_ci lwip_md5_init(&md5_ctx); 105195972f6Sopenharmony_ci lwip_md5_starts(&md5_ctx); 106195972f6Sopenharmony_ci lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); 107195972f6Sopenharmony_ci if (rand_data) { 108195972f6Sopenharmony_ci lwip_md5_update(&md5_ctx, (u_char *)rand_data, rand_len); 109195972f6Sopenharmony_ci } else { 110195972f6Sopenharmony_ci struct { 111195972f6Sopenharmony_ci /* INCLUDE fields for any system sources of randomness */ 112195972f6Sopenharmony_ci u32_t jiffies; 113195972f6Sopenharmony_ci#ifdef LWIP_RAND 114195972f6Sopenharmony_ci u32_t rand; 115195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 116195972f6Sopenharmony_ci } sys_data; 117195972f6Sopenharmony_ci magic_randomseed += sys_jiffies(); 118195972f6Sopenharmony_ci sys_data.jiffies = magic_randomseed; 119195972f6Sopenharmony_ci#ifdef LWIP_RAND 120195972f6Sopenharmony_ci sys_data.rand = LWIP_RAND(); 121195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 122195972f6Sopenharmony_ci /* Load sys_data fields here. */ 123195972f6Sopenharmony_ci lwip_md5_update(&md5_ctx, (u_char *)&sys_data, sizeof(sys_data)); 124195972f6Sopenharmony_ci } 125195972f6Sopenharmony_ci lwip_md5_finish(&md5_ctx, (u_char *)magic_randpool); 126195972f6Sopenharmony_ci lwip_md5_free(&md5_ctx); 127195972f6Sopenharmony_ci/* LWIP_DEBUGF(LOG_INFO, ("magic_churnrand: -> 0\n")); */ 128195972f6Sopenharmony_ci} 129195972f6Sopenharmony_ci 130195972f6Sopenharmony_ci/* 131195972f6Sopenharmony_ci * Initialize the random number generator. 132195972f6Sopenharmony_ci */ 133195972f6Sopenharmony_civoid magic_init(void) { 134195972f6Sopenharmony_ci magic_churnrand(NULL, 0); 135195972f6Sopenharmony_ci} 136195972f6Sopenharmony_ci 137195972f6Sopenharmony_ci/* 138195972f6Sopenharmony_ci * Randomize our random seed value. 139195972f6Sopenharmony_ci */ 140195972f6Sopenharmony_civoid magic_randomize(void) { 141195972f6Sopenharmony_ci magic_churnrand(NULL, 0); 142195972f6Sopenharmony_ci} 143195972f6Sopenharmony_ci 144195972f6Sopenharmony_ci/* 145195972f6Sopenharmony_ci * magic_random_bytes - Fill a buffer with random bytes. 146195972f6Sopenharmony_ci * 147195972f6Sopenharmony_ci * Use the random pool to generate random data. This degrades to pseudo 148195972f6Sopenharmony_ci * random when used faster than randomness is supplied using magic_churnrand(). 149195972f6Sopenharmony_ci * Note: It's important that there be sufficient randomness in magic_randpool 150195972f6Sopenharmony_ci * before this is called for otherwise the range of the result may be 151195972f6Sopenharmony_ci * narrow enough to make a search feasible. 152195972f6Sopenharmony_ci * 153195972f6Sopenharmony_ci * Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427 154195972f6Sopenharmony_ci * 155195972f6Sopenharmony_ci * XXX Why does he not just call magic_churnrand() for each block? Probably 156195972f6Sopenharmony_ci * so that you don't ever publish the seed which could possibly help 157195972f6Sopenharmony_ci * predict future values. 158195972f6Sopenharmony_ci * XXX Why don't we preserve md5 between blocks and just update it with 159195972f6Sopenharmony_ci * magic_randcount each time? Probably there is a weakness but I wish that 160195972f6Sopenharmony_ci * it was documented. 161195972f6Sopenharmony_ci */ 162195972f6Sopenharmony_civoid magic_random_bytes(unsigned char *buf, u32_t buf_len) { 163195972f6Sopenharmony_ci lwip_md5_context md5_ctx; 164195972f6Sopenharmony_ci u_char tmp[MD5_HASH_SIZE]; 165195972f6Sopenharmony_ci u32_t n; 166195972f6Sopenharmony_ci 167195972f6Sopenharmony_ci while (buf_len > 0) { 168195972f6Sopenharmony_ci lwip_md5_init(&md5_ctx); 169195972f6Sopenharmony_ci lwip_md5_starts(&md5_ctx); 170195972f6Sopenharmony_ci lwip_md5_update(&md5_ctx, (u_char *)magic_randpool, sizeof(magic_randpool)); 171195972f6Sopenharmony_ci lwip_md5_update(&md5_ctx, (u_char *)&magic_randcount, sizeof(magic_randcount)); 172195972f6Sopenharmony_ci lwip_md5_finish(&md5_ctx, tmp); 173195972f6Sopenharmony_ci lwip_md5_free(&md5_ctx); 174195972f6Sopenharmony_ci magic_randcount++; 175195972f6Sopenharmony_ci n = LWIP_MIN(buf_len, MD5_HASH_SIZE); 176195972f6Sopenharmony_ci MEMCPY(buf, tmp, n); 177195972f6Sopenharmony_ci buf += n; 178195972f6Sopenharmony_ci buf_len -= n; 179195972f6Sopenharmony_ci } 180195972f6Sopenharmony_ci} 181195972f6Sopenharmony_ci 182195972f6Sopenharmony_ci/* 183195972f6Sopenharmony_ci * Return a new random number. 184195972f6Sopenharmony_ci */ 185195972f6Sopenharmony_ciu32_t magic(void) { 186195972f6Sopenharmony_ci u32_t new_rand; 187195972f6Sopenharmony_ci 188195972f6Sopenharmony_ci magic_random_bytes((unsigned char *)&new_rand, sizeof(new_rand)); 189195972f6Sopenharmony_ci 190195972f6Sopenharmony_ci return new_rand; 191195972f6Sopenharmony_ci} 192195972f6Sopenharmony_ci 193195972f6Sopenharmony_ci#else /* PPP_MD5_RANDM */ 194195972f6Sopenharmony_ci 195195972f6Sopenharmony_ci/*****************************/ 196195972f6Sopenharmony_ci/*** LOCAL DATA STRUCTURES ***/ 197195972f6Sopenharmony_ci/*****************************/ 198195972f6Sopenharmony_ci#ifndef LWIP_RAND 199195972f6Sopenharmony_cistatic int magic_randomized; /* Set when truely randomized. */ 200195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 201195972f6Sopenharmony_cistatic u32_t magic_randomseed; /* Seed used for random number generation. */ 202195972f6Sopenharmony_ci 203195972f6Sopenharmony_ci 204195972f6Sopenharmony_ci/***********************************/ 205195972f6Sopenharmony_ci/*** PUBLIC FUNCTION DEFINITIONS ***/ 206195972f6Sopenharmony_ci/***********************************/ 207195972f6Sopenharmony_ci 208195972f6Sopenharmony_ci/* 209195972f6Sopenharmony_ci * Initialize the random number generator. 210195972f6Sopenharmony_ci * 211195972f6Sopenharmony_ci * Here we attempt to compute a random number seed but even if 212195972f6Sopenharmony_ci * it isn't random, we'll randomize it later. 213195972f6Sopenharmony_ci * 214195972f6Sopenharmony_ci * The current method uses the fields from the real time clock, 215195972f6Sopenharmony_ci * the idle process counter, the millisecond counter, and the 216195972f6Sopenharmony_ci * hardware timer tick counter. When this is invoked 217195972f6Sopenharmony_ci * in startup(), then the idle counter and timer values may 218195972f6Sopenharmony_ci * repeat after each boot and the real time clock may not be 219195972f6Sopenharmony_ci * operational. Thus we call it again on the first random 220195972f6Sopenharmony_ci * event. 221195972f6Sopenharmony_ci */ 222195972f6Sopenharmony_civoid magic_init(void) { 223195972f6Sopenharmony_ci magic_randomseed += sys_jiffies(); 224195972f6Sopenharmony_ci#ifndef LWIP_RAND 225195972f6Sopenharmony_ci /* Initialize the Borland random number generator. */ 226195972f6Sopenharmony_ci srand((unsigned)magic_randomseed); 227195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 228195972f6Sopenharmony_ci} 229195972f6Sopenharmony_ci 230195972f6Sopenharmony_ci/* 231195972f6Sopenharmony_ci * magic_init - Initialize the magic number generator. 232195972f6Sopenharmony_ci * 233195972f6Sopenharmony_ci * Randomize our random seed value. Here we use the fact that 234195972f6Sopenharmony_ci * this function is called at *truely random* times by the polling 235195972f6Sopenharmony_ci * and network functions. Here we only get 16 bits of new random 236195972f6Sopenharmony_ci * value but we use the previous value to randomize the other 16 237195972f6Sopenharmony_ci * bits. 238195972f6Sopenharmony_ci */ 239195972f6Sopenharmony_civoid magic_randomize(void) { 240195972f6Sopenharmony_ci#ifndef LWIP_RAND 241195972f6Sopenharmony_ci if (!magic_randomized) { 242195972f6Sopenharmony_ci magic_randomized = !0; 243195972f6Sopenharmony_ci magic_init(); 244195972f6Sopenharmony_ci /* The initialization function also updates the seed. */ 245195972f6Sopenharmony_ci } else { 246195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 247195972f6Sopenharmony_ci magic_randomseed += sys_jiffies(); 248195972f6Sopenharmony_ci#ifndef LWIP_RAND 249195972f6Sopenharmony_ci } 250195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 251195972f6Sopenharmony_ci} 252195972f6Sopenharmony_ci 253195972f6Sopenharmony_ci/* 254195972f6Sopenharmony_ci * Return a new random number. 255195972f6Sopenharmony_ci * 256195972f6Sopenharmony_ci * Here we use the Borland rand() function to supply a pseudo random 257195972f6Sopenharmony_ci * number which we make truely random by combining it with our own 258195972f6Sopenharmony_ci * seed which is randomized by truely random events. 259195972f6Sopenharmony_ci * Thus the numbers will be truely random unless there have been no 260195972f6Sopenharmony_ci * operator or network events in which case it will be pseudo random 261195972f6Sopenharmony_ci * seeded by the real time clock. 262195972f6Sopenharmony_ci */ 263195972f6Sopenharmony_ciu32_t magic(void) { 264195972f6Sopenharmony_ci#ifdef LWIP_RAND 265195972f6Sopenharmony_ci return LWIP_RAND() + magic_randomseed; 266195972f6Sopenharmony_ci#else /* LWIP_RAND */ 267195972f6Sopenharmony_ci return ((u32_t)rand() << 16) + (u32_t)rand() + magic_randomseed; 268195972f6Sopenharmony_ci#endif /* LWIP_RAND */ 269195972f6Sopenharmony_ci} 270195972f6Sopenharmony_ci 271195972f6Sopenharmony_ci/* 272195972f6Sopenharmony_ci * magic_random_bytes - Fill a buffer with random bytes. 273195972f6Sopenharmony_ci */ 274195972f6Sopenharmony_civoid magic_random_bytes(unsigned char *buf, u32_t buf_len) { 275195972f6Sopenharmony_ci u32_t new_rand, n; 276195972f6Sopenharmony_ci 277195972f6Sopenharmony_ci while (buf_len > 0) { 278195972f6Sopenharmony_ci new_rand = magic(); 279195972f6Sopenharmony_ci n = LWIP_MIN(buf_len, sizeof(new_rand)); 280195972f6Sopenharmony_ci MEMCPY(buf, &new_rand, n); 281195972f6Sopenharmony_ci buf += n; 282195972f6Sopenharmony_ci buf_len -= n; 283195972f6Sopenharmony_ci } 284195972f6Sopenharmony_ci} 285195972f6Sopenharmony_ci#endif /* PPP_MD5_RANDM */ 286195972f6Sopenharmony_ci 287195972f6Sopenharmony_ci/* 288195972f6Sopenharmony_ci * Return a new random number between 0 and (2^pow)-1 included. 289195972f6Sopenharmony_ci */ 290195972f6Sopenharmony_ciu32_t magic_pow(u8_t pow) { 291195972f6Sopenharmony_ci return magic() & ~(~0UL<<pow); 292195972f6Sopenharmony_ci} 293195972f6Sopenharmony_ci 294195972f6Sopenharmony_ci#endif /* PPP_SUPPORT */ 295