From 0483b8dfa8dc9dc01b6c2451bfd90867b1114f9f Mon Sep 17 00:00:00 2001 From: rasky Date: Tue, 28 Sep 2010 18:00:42 +0000 Subject: [PATCH] SEC: Add ISAAC PRNG implementation git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4333 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/sec/prng/isaac.c | 202 ++++++++++++++++++++++++++++++++++++++++ bertos/sec/prng/isaac.h | 77 +++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 bertos/sec/prng/isaac.c create mode 100644 bertos/sec/prng/isaac.h diff --git a/bertos/sec/prng/isaac.c b/bertos/sec/prng/isaac.c new file mode 100644 index 00000000..d4246f71 --- /dev/null +++ b/bertos/sec/prng/isaac.c @@ -0,0 +1,202 @@ +/** + * \file + * + * + * \brief ISAAC implementation + * \author Giovanni Bajo + * + */ + +/* +------------------------------------------------------------------------------ +rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain. +MODIFIED: + 960327: Creation (addition of randinit, really) + 970719: use context, not global variables, for internal state + 980324: added main (ifdef'ed out), also rearranged randinit() + 010626: Note that this is public domain +------------------------------------------------------------------------------ +*/ + +#include "isaac.h" +#include +#include +#include +#include + +typedef uint32_t ub4; +typedef uint16_t ub2; +typedef uint8_t ub1; + +#define ind(mm,x) (*(ub4 *)((ub1 *)(mm) + ((x) & ((CONFIG_ISAAC_RANDSIZ-1)<<2)))) +#define rngstep(mix,a,b,mm,m,m2,r,x) \ +{ \ + x = *m; \ + a = (a^(mix)) + *(m2++); \ + *(m++) = y = ind(mm,x) + a + b; \ + *(r++) = b = ind(mm,y>>CONFIG_ISAAC_RANDSIZL) + x; \ +} + +static void isaac(ISAAC_Context *ctx) +{ + register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend; + mm=ctx->randmem; r=ctx->randrsl; + a = ctx->randa; b = ctx->randb + (++ctx->randc); + for (m = mm, mend = m2 = m+(CONFIG_ISAAC_RANDSIZ/2); m>6 , a, b, mm, m, m2, r, x); + rngstep( a<<2 , a, b, mm, m, m2, r, x); + rngstep( a>>16, a, b, mm, m, m2, r, x); + } + for (m2 = mm; m2>6 , a, b, mm, m, m2, r, x); + rngstep( a<<2 , a, b, mm, m, m2, r, x); + rngstep( a>>16, a, b, mm, m, m2, r, x); + } + ctx->randb = b; ctx->randa = a; +} + + +#define mix(a,b,c,d,e,f,g,h) \ +{ \ + a^=b<<11; d+=a; b+=c; \ + b^=c>>2; e+=b; c+=d; \ + c^=d<<8; f+=c; d+=e; \ + d^=e>>16; g+=d; e+=f; \ + e^=f<<10; h+=e; f+=g; \ + f^=g>>4; a+=f; g+=h; \ + g^=h<<8; b+=g; h+=a; \ + h^=a>>9; c+=h; a+=b; \ +} + +static void ISAAC_reseed(PRNG *ctx_, const uint8_t *seed) +{ + ISAAC_Context *ctx = (ISAAC_Context *)ctx_; + int i; + ub4 a,b,c,d,e,f,g,h; + ub4 *m,*r; + + // Copy seed over half of randrsl, to reuse half of last-generated + // data as seed. + memcpy(ctx->randrsl, seed, sizeof(ctx->randrsl)/2); + + ctx->randa = ctx->randb = ctx->randc = 0; + m=ctx->randmem; + r=ctx->randrsl; + a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ + + for (i=0; i<4; ++i) /* scramble it */ + { + mix(a,b,c,d,e,f,g,h); + } + + /* initialize using the contents of r[] as the seed */ + for (i=0; irandrsl) == CONFIG_ISAAC_RANDSIZ*4); + + while (len) + { + ASSERT(ctx->randcnt <= CONFIG_ISAAC_RANDSIZ*4); + + if (ctx->randcnt == CONFIG_ISAAC_RANDSIZ*4) + { + isaac(ctx); + ctx->randcnt = 0; + } + + size_t L = MIN(len, CONFIG_ISAAC_RANDSIZ*4 - (size_t)ctx->randcnt); + memcpy(data, (uint8_t*)ctx->randrsl + ctx->randcnt, L); + data += L; + ctx->randcnt += L; + len -= L; + } +} + + +/**********************************************************************/ + +void ISAAC_init(ISAAC_Context *ctx) +{ + ctx->prng.reseed = ISAAC_reseed; + ctx->prng.generate = ISAAC_generate; + ctx->prng.seed_len = sizeof(ctx->randrsl) / 2; + + ctx->randcnt = CONFIG_ISAAC_RANDSIZ*4; + memset(ctx->randrsl, 0, sizeof(ctx->randrsl)); +} + + + + +#ifdef NEVER +int main() +{ + ub4 i,j; + randctx ctx; + ctx.randa=ctx.randb=ctx.randc=(ub4)0; + for (i=0; i<256; ++i) ctx.randrsl[i]=(ub4)0; + randinit(&ctx, TRUE); + for (i=0; i<2; ++i) + { + isaac(&ctx); + for (j=0; j<256; ++j) + { + printf("%.8lx",ctx.randrsl[j]); + if ((j&7)==7) printf("\n"); + } + } +} +#endif diff --git a/bertos/sec/prng/isaac.h b/bertos/sec/prng/isaac.h new file mode 100644 index 00000000..c9f9663e --- /dev/null +++ b/bertos/sec/prng/isaac.h @@ -0,0 +1,77 @@ +/** + * \file + * + * + * \brief ISAAC implementation + * \author Giovanni Bajo + * + */ + +#ifndef SEC_PRNG_ISAAC_H +#define SEC_PRNG_ISAAC_H + +#include + +/** + * Size of the internal ISAAC state (in 32-bit words). + * + * ISAAC is known to generate unbiased data as follows: + * * 3 words: 2^37 unbiased values + * * 4 words: 2^45 unbiased values + * * 5 words: 2^53 unbiased values + * * 6 words: 2^61 unbiased values + * * 7 words: 2^69 unbiased values + * * 8 words: 2^77 unbiased values + * + * The period of the generator is usually much longer, but it is + * obviously uninteresting for a CSPRNG. + */ +#define CONFIG_ISAAC_RANDSIZL (3) +#define CONFIG_ISAAC_RANDSIZ (1<<(CONFIG_ISAAC_RANDSIZL)) + +typedef struct +{ + PRNG prng; + uint32_t randcnt; + uint32_t randrsl[CONFIG_ISAAC_RANDSIZ]; + uint32_t randmem[CONFIG_ISAAC_RANDSIZ]; + uint32_t randa; + uint32_t randb; + uint32_t randc; +} ISAAC_Context; + +void ISAAC_init(ISAAC_Context *ctx); + +#define ISAAC_stackinit(...) \ + ({ ISAAC_Context *ctx = alloca(sizeof(ISAAC_Context)); ISAAC_init(ctx , ##__VA_ARGS__); &ctx->prng; }) + + +#endif /* SEC_PRNG_ISAAC_H */ -- 2.25.1