4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
33 * \brief ISAAC implementation
34 * \author Giovanni Bajo <rasky@develer.com>
39 ------------------------------------------------------------------------------
40 rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain.
42 960327: Creation (addition of randinit, really)
43 970719: use context, not global variables, for internal state
44 980324: added main (ifdef'ed out), also rearranged randinit()
45 010626: Note that this is public domain
46 ------------------------------------------------------------------------------
51 #include <cfg/compiler.h>
52 #include <cfg/macros.h>
59 #define ind(mm,x) (*(ub4 *)((ub1 *)(mm) + ((x) & ((CONFIG_ISAAC_RANDSIZ-1)<<2))))
60 #define rngstep(mix,a,b,mm,m,m2,r,x) \
63 a = (a^(mix)) + *(m2++); \
64 *(m++) = y = ind(mm,x) + a + b; \
65 *(r++) = b = ind(mm,y>>CONFIG_ISAAC_RANDSIZL) + x; \
68 static void isaac(IsaacContext *ctx)
70 register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
71 mm=ctx->randmem; r=ctx->randrsl;
72 a = ctx->randa; b = ctx->randb + (++ctx->randc);
73 for (m = mm, mend = m2 = m+(CONFIG_ISAAC_RANDSIZ/2); m<mend; )
75 rngstep( a<<13, a, b, mm, m, m2, r, x);
76 rngstep( a>>6 , a, b, mm, m, m2, r, x);
77 rngstep( a<<2 , a, b, mm, m, m2, r, x);
78 rngstep( a>>16, a, b, mm, m, m2, r, x);
80 for (m2 = mm; m2<mend; )
82 rngstep( a<<13, a, b, mm, m, m2, r, x);
83 rngstep( a>>6 , a, b, mm, m, m2, r, x);
84 rngstep( a<<2 , a, b, mm, m, m2, r, x);
85 rngstep( a>>16, a, b, mm, m, m2, r, x);
87 ctx->randb = b; ctx->randa = a;
91 #define mix(a,b,c,d,e,f,g,h) \
93 a^=b<<11; d+=a; b+=c; \
94 b^=c>>2; e+=b; c+=d; \
95 c^=d<<8; f+=c; d+=e; \
96 d^=e>>16; g+=d; e+=f; \
97 e^=f<<10; h+=e; f+=g; \
98 f^=g>>4; a+=f; g+=h; \
99 g^=h<<8; b+=g; h+=a; \
100 h^=a>>9; c+=h; a+=b; \
103 static void isaac_reseed(PRNG *ctx_, const uint8_t *seed)
105 IsaacContext *ctx = (IsaacContext *)ctx_;
110 // XOR the new seed over the current state, so to depend on
111 // the previously-generated output.
112 xor_block(ctx->randrsl, ctx->randrsl, seed, sizeof(ctx->randrsl));
114 ctx->randa = ctx->randb = ctx->randc = 0;
117 a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */
119 for (i=0; i<4; ++i) /* scramble it */
121 mix(a,b,c,d,e,f,g,h);
124 /* initialize using the contents of r[] as the seed */
125 for (i=0; i<CONFIG_ISAAC_RANDSIZ; i+=8)
127 a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
128 e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
129 mix(a,b,c,d,e,f,g,h);
130 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
131 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
133 /* do a second pass to make all of the seed affect all of m */
134 for (i=0; i<CONFIG_ISAAC_RANDSIZ; i+=8)
136 a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
137 e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
138 mix(a,b,c,d,e,f,g,h);
139 m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
140 m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
144 static void isaac_generate(PRNG *ctx_, uint8_t *data, size_t len)
146 IsaacContext *ctx = (IsaacContext *)ctx_;
148 STATIC_ASSERT(sizeof(ctx->randrsl) == CONFIG_ISAAC_RANDSIZ*4);
152 ASSERT(ctx->randcnt <= CONFIG_ISAAC_RANDSIZ*4);
154 if (ctx->randcnt == CONFIG_ISAAC_RANDSIZ*4)
160 size_t L = MIN(len, CONFIG_ISAAC_RANDSIZ*4 - (size_t)ctx->randcnt);
161 memcpy(data, (uint8_t*)ctx->randrsl + ctx->randcnt, L);
169 /**********************************************************************/
171 void isaac_init(IsaacContext *ctx)
173 ctx->prng.reseed = isaac_reseed;
174 ctx->prng.generate = isaac_generate;
175 ctx->prng.seed_len = sizeof(ctx->randrsl);
176 ctx->prng.seeded = 0;
178 ctx->randcnt = CONFIG_ISAAC_RANDSIZ*4;
179 memset(ctx->randrsl, 0, sizeof(ctx->randrsl));
190 ctx.randa=ctx.randb=ctx.randc=(ub4)0;
191 for (i=0; i<256; ++i) ctx.randrsl[i]=(ub4)0;
192 randinit(&ctx, TRUE);
196 for (j=0; j<256; ++j)
198 printf("%.8lx",ctx.randrsl[j]);
199 if ((j&7)==7) printf("\n");