SEC: Add ISAAC PRNG implementation
authorrasky <rasky@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 28 Sep 2010 18:00:42 +0000 (18:00 +0000)
committerrasky <rasky@38d2e660-2303-0410-9eaa-f027e97ec537>
Tue, 28 Sep 2010 18:00:42 +0000 (18:00 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4333 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/sec/prng/isaac.c [new file with mode: 0644]
bertos/sec/prng/isaac.h [new file with mode: 0644]

diff --git a/bertos/sec/prng/isaac.c b/bertos/sec/prng/isaac.c
new file mode 100644 (file)
index 0000000..d4246f7
--- /dev/null
@@ -0,0 +1,202 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief ISAAC implementation
+ * \author Giovanni Bajo <rasky@develer.com>
+ * 
+ */
+
+/*
+------------------------------------------------------------------------------
+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 <sec/prng.h>
+#include <cfg/compiler.h>
+#include <cfg/macros.h>
+#include <string.h>
+
+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<mend; )
+       {
+               rngstep( a<<13, a, b, mm, m, m2, r, x);
+               rngstep( a>>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<mend; )
+       {
+               rngstep( a<<13, a, b, mm, m, m2, r, x);
+               rngstep( a>>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; i<CONFIG_ISAAC_RANDSIZ; i+=8)
+       {
+               a+=r[i  ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
+               e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
+               mix(a,b,c,d,e,f,g,h);
+               m[i  ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
+               m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
+       }
+       /* do a second pass to make all of the seed affect all of m */
+       for (i=0; i<CONFIG_ISAAC_RANDSIZ; i+=8)
+       {
+               a+=m[i  ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
+               e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
+               mix(a,b,c,d,e,f,g,h);
+               m[i  ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
+               m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
+       }
+}
+
+static void ISAAC_generate(PRNG *ctx_, uint8_t *data, size_t len)
+{
+       ISAAC_Context *ctx = (ISAAC_Context *)ctx_;
+
+       STATIC_ASSERT(sizeof(ctx->randrsl) == 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 (file)
index 0000000..c9f9663
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \brief ISAAC implementation
+ * \author Giovanni Bajo <rasky@develer.com>
+ * 
+ */
+
+#ifndef SEC_PRNG_ISAAC_H
+#define SEC_PRNG_ISAAC_H
+
+#include <sec/prng.h>
+
+/**
+ * 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 */