📄 prng.c
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/common/lib/prng.c,v 1.3 2003/01/16 18:18:56 josh Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved. Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** * Copyright 1997 Epilogue Technology Corporation. * Copyright 1998-1999 Integrated Systems, Inc. * All rights reserved. ****************************************************************************//* * $Log: prng.c,v $ * Revision 1.3 2003/01/16 18:18:56 josh * directory structure shifting * * Revision 1.2 2001/11/06 22:15:53 tneale * Fixed for newest file layout * * Revision 1.1.1.1 2001/11/05 17:48:39 tneale * Tornado shuffle * * Revision 1.17 2001/01/19 22:21:31 paul * Update copyright. * * Revision 1.16 2000/03/17 00:16:55 meister * Update copyright message * * Revision 1.15 2000/03/13 21:21:47 paul * Removed some code that we are no longer working on. * * Revision 1.14 1999/04/28 23:53:24 sra * Clean up various minor installation option glitches. * * Revision 1.13 1999/03/06 06:54:36 paul * moved common_init from prng.c to cmn_init.c * * Revision 1.11.2.1 1999/01/04 20:57:58 wes * Shut up purify. * * Revision 1.11 1998/09/11 16:30:41 paul * Auto-initialize common library. * * Revision 1.10 1998/06/25 20:40:06 sra * Fix CAD-UL warning in prng_init(). * * Revision 1.9 1998/02/25 04:43:28 sra * Update copyrights. * * Revision 1.8 1997/10/30 16:42:34 sra * Fix copyright date. * * Revision 1.7 1997/08/21 17:23:43 sra * Begin moving configuration stuff that's common to all products to common.h * Minor cleanups to common/lib/prng.c. Add pnrg seed function to snarkbsd. * * Revision 1.6 1997/08/19 23:05:54 meister * Made some variables static that were global (and shouldnt have been). * Generated reasonable values for the two magic constants PRNG_MAGIC[12] * * Revision 1.5 1997/08/14 21:42:13 meister * ifdef'd out the linear congruential generator, and added the crypto-strong * one. * * Revision 1.4 1997/08/14 16:04:39 lowell * boilerplate * *//* [clearcase]modification history-------------------01b,20apr05,job update copyright notices01a,11dec03,job fix copyright statements*/#ifndef EPILOGUE_INSTALL_H#include <wrn/wm/common/install.h>#endif#ifndef COMMON_CONFIG_H#include <wrn/wm/common/config.h>#endif#ifndef COMMON_PRNG_H#include <wrn/wm/common/prng.h>#endif#ifndef __MD5_INCLUDE__#include <wrn/wm/common/md5.h>#endif#ifndef COMMON_GLUE_H#include <wrn/wm/common/glue.h>#endif/* * This file implements a cryptographically strong random number generator. * The algorithm is based on the ANSI X9.17 generator. Keyed MD5 is used * as the basic transform rather than TDES. The DT value is augmented with * a monotonically increasing counter. See [Stallings - Network and * Internetwork Security pp 102-103] or ANSI X9.17 Appendix C. */static void prng_iterate (void);/* * these next 2 bits of magic are used to seed the generator with * less than 32 bytes of randomness. If the user hands in N < 32 bytes (call * them "B") we generate MD5 (MAGIC1 "+" B "+" MAGIC1), and * MD5 (MAGIC2 "+" B "+" MAGIC2), and combine them to get our needed 32 bytes. * The actual values here are *not* of any importance, although having a * reasonably "random" bit distribution is useful. These were generated by * running some real-time system statistics through MD5. */static bits8_t PRNG_MAGIC1 [] ={ 0xb4, 0x33, 0x4b, 0xf5, 0x9b, 0x7a, 0x24, 0x19, 0x8c, 0x04, 0xa5, 0xd1, 0x1e, 0xab, 0xa2, 0xe9 };static bits8_t PRNG_MAGIC2 [] = { 0xaa, 0x9b, 0x49, 0xd4, 0x0f, 0x4c, 0xa7, 0x1b, 0x1d, 0x0e, 0x83, 0xd6, 0xe7, 0x9c, 0xab, 0xf8};#define PRNG_SEEDBYTES_NEEDED 32static MD5_CTX PRNG_MD5_CTX;/* new seed buffer for prng_get_seed () */static bits8_t PRNG_SB [PRNG_SEEDBYTES_NEEDED]; static bits8_t PRNG_MD5_K [16]; /* MD5 keyed hash key */static bits8_t PRNG_SV [16]; /* current seed value */static bits8_t PRNG_R [16]; /* current random pool */static bits32_t PRNG_DT; /* "date+time" value */static bits32_t PRNG_CNT; /* counter; increments with each call */static bits8_t PRNG_N; /* number of "random" bytes currently available */static bits8_t PRNG_INJIDX; /* index of PRNG_SV where prng_inject_random8 will xor next random input into *//* * Initialize the prng system. This involves calling out for seed bytes. 32 * of them, in fact. */void prng_init (void){ bits8_t seedvalues [PRNG_SEEDBYTES_NEEDED]; bits32_t actual; MEMSET(seedvalues, 0, PRNG_SEEDBYTES_NEEDED); actual = GLUE_SEED_PRNG(seedvalues, PRNG_SEEDBYTES_NEEDED); if (actual < PRNG_SEEDBYTES_NEEDED) { MD5Init (&PRNG_MD5_CTX); MD5Update (&PRNG_MD5_CTX, PRNG_MAGIC1, 16); if (actual > 0) MD5Update (&PRNG_MD5_CTX, (bits8_t *) seedvalues, actual); MD5Update (&PRNG_MD5_CTX, PRNG_MAGIC1, 16); MD5Final (&PRNG_MD5_CTX); MEMCPY(PRNG_MD5_K, PRNG_MD5_CTX.digest, 16); MD5Init (&PRNG_MD5_CTX); MD5Update (&PRNG_MD5_CTX, PRNG_MAGIC2, 16); MD5Update (&PRNG_MD5_CTX, (bits8_t *) seedvalues, actual); MD5Update (&PRNG_MD5_CTX, PRNG_MAGIC2, 16); MD5Final (&PRNG_MD5_CTX); MEMCPY(PRNG_SV, PRNG_MD5_CTX.digest, 16); MEMCPY(&PRNG_CNT, seedvalues, 4); } else { MEMCPY(PRNG_SV, seedvalues, 16); MEMCPY(PRNG_MD5_K, seedvalues + 16, 16); MEMCPY(&PRNG_CNT, seedvalues, 4); } PRNG_DT = GLUE_NOW(); PRNG_N = PRNG_INJIDX = 0; prng_iterate (); /* kick start the PRNG */} /* * compute next seed value and state */static void prng_iterate (void){ int i; bits8_t *p, *q; bits8_t digest [16]; /* step 1. R = MD5_K (MD5_K ((DT concat (++CNT)) XOR SV)) */ /* digest <-- MD5 ((DT concat (++CNT)) XOR SV */ ++PRNG_CNT; PRNG_DT = GLUE_NOW(); MD5Init (&PRNG_MD5_CTX); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Update (&PRNG_MD5_CTX, (bits8_t *) &PRNG_DT, 4); MD5Update (&PRNG_MD5_CTX, (bits8_t *) &PRNG_CNT, 4); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Final (&PRNG_MD5_CTX); MEMCPY(digest, PRNG_MD5_CTX.digest, 16); /* PRNG_SV <-- (PRNG_SV XOR digest) */ /* leave digest alone as we'll need it again when we compute new SV */ for (i = 0, p = PRNG_SV, q = digest; i < 16 ; i++) *p++ ^= *q++; /* PRNG_R <-- MD5 (PRNG_SV) */ MD5Init (&PRNG_MD5_CTX); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Update (&PRNG_MD5_CTX, PRNG_SV, 16); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Final (&PRNG_MD5_CTX); MEMCPY(PRNG_R, PRNG_MD5_CTX.digest, 16); /* * step 2. SV = MD5_K (MD5_K ((DT concat (++CNT)) XOR R)) * * digest is still MD5_K ((DT concat (++CNT)), so we dont need another * MD5 operation */ /* PRNG_SV <-- (PRNG_SV XOR digest) */ for (i = 0, p = PRNG_R, q = digest; i < 16 ; i++) *q++ ^= *p++; MD5Init (&PRNG_MD5_CTX); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Update (&PRNG_MD5_CTX, (bits8_t *) digest, 16); MD5Update (&PRNG_MD5_CTX, PRNG_MD5_K, 16); MD5Final (&PRNG_MD5_CTX); MEMCPY(PRNG_SV, PRNG_MD5_CTX.digest, 16); /* now we have another 16 bytes of usable R */ PRNG_N = 16;}/* * hand back a "random" byte */bits8_t prng_random8 (void){ if (!PRNG_N) prng_iterate (); return PRNG_R [--PRNG_N];}/* * fill up a buffer with "random" bytes */void prng_random (bits8_t *buf, int N){ while (N--) *buf++ = prng_random8 ();}void prng_get_seed(bits8_t **buffer, int * bufsize){ prng_iterate (); MEMCPY(PRNG_SB, PRNG_SV, 16); MEMCPY(PRNG_SB + 16, PRNG_R, 16); prng_iterate (); *buffer = PRNG_SB; *bufsize = PRNG_SEEDBYTES_NEEDED;}void prng_inject_random8 (bits8_t in){ PRNG_SV [PRNG_INJIDX & 0xF] ^= in; PRNG_INJIDX++;#ifndef PRNG_INJECT_IMMEDIATE_EFFECT prng_iterate ();#else if (!(PRNG_INJIDX & 0xF)) prng_iterate ();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -