diff --git a/src/Makefile.am b/src/Makefile.am index 9a719ef..f4fea2f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,5 +6,5 @@ AM_LDFLAGS = # this lists the binaries to produce, the (non-PHONY, binary) targets in # the previous manual Makefile bin_PROGRAMS = nwipe -nwipe_SOURCES = context.h isaac_rand/isaac_rand.c logging.h options.h prng.h version.h temperature.h nwipe.c gui.c isaac_rand/isaac_rand.h method.h pass.c device.c gui.h isaac_rand/isaac_standard.h mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c +nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c nwipe_LDADD = $(PARTED_LIBS) diff --git a/src/gui.c b/src/gui.c index 666df8b..cd1816c 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1464,10 +1464,11 @@ void nwipe_gui_prng( void ) extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; + extern nwipe_prng_t nwipe_isaac64; extern int terminate_signal; /* The number of implemented PRNGs. */ - const int count = 2; + const int count = 3; /* The first tabstop. */ const int tab1 = 2; @@ -1497,6 +1498,10 @@ void nwipe_gui_prng( void ) { focus = 1; } + if( nwipe_options.prng == &nwipe_isaac64 ) + { + focus = 2; + } do { @@ -1506,15 +1511,16 @@ void nwipe_gui_prng( void ) nwipe_gui_create_all_windows_on_terminal_resize( 0, selection_footer ); /* Initialize the working row. */ - yy = 2; + yy = 3; /* Print the options. */ mvwprintw( main_window, yy++, tab1, " %s", nwipe_twister.label ); mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac.label ); + mvwprintw( main_window, yy++, tab1, " %s", nwipe_isaac64.label ); mvwprintw( main_window, yy++, tab1, "" ); /* Print the cursor. */ - mvwaddch( main_window, 2 + focus, tab1, ACS_RARROW ); + mvwaddch( main_window, 3 + focus, tab1, ACS_RARROW ); switch( focus ) { @@ -1564,6 +1570,34 @@ void nwipe_gui_prng( void ) yy++, tab1, " " ); + mvwprintw( main_window, + yy++, + tab1, + "Performs best on a 32-bit CPU. Use ISAAC-64 if this system has a 64-bit CPU." ); + break; + + case 2: + + mvwprintw( main_window, + yy++, + tab1, + "ISAAC-64, by Bob Jenkins, is like 32-bit ISAAC, but with a minimum period of" ); + mvwprintw( main_window, + yy++, + tab1, + "2^77 and an expected period of 2^16583. It is difficult to recover the " ); + mvwprintw( main_window, + yy++, + tab1, + "initial PRNG state by cryptanalysis of the ISAAC-64 stream. " ); + mvwprintw( main_window, + yy++, + tab1, + " " ); + mvwprintw( main_window, + yy++, + tab1, + "Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " ); break; } /* switch */ @@ -1622,6 +1656,10 @@ void nwipe_gui_prng( void ) { nwipe_options.prng = &nwipe_isaac; } + if( focus == 2 ) + { + nwipe_options.prng = &nwipe_isaac64; + } return; case KEY_BACKSPACE: @@ -1791,10 +1829,6 @@ void nwipe_gui_verify( void ) { nwipe_options.verify = focus; } - if( nwipe_options.verify != NWIPE_VERIFY_NONE ) - { - nwipe_options.noblank = 0; - } return; case KEY_BACKSPACE: diff --git a/src/isaac_rand/isaac64.c b/src/isaac_rand/isaac64.c new file mode 100644 index 0000000..3e4203b --- /dev/null +++ b/src/isaac_rand/isaac64.c @@ -0,0 +1,119 @@ +/* +------------------------------------------------------------------------------ +isaac64.c: My random number generator for 64-bit machines. +By Bob Jenkins, 1996. Public Domain. +------------------------------------------------------------------------------ +*/ +#ifndef STANDARD +#include "isaac_standard.h" +#endif +#ifndef ISAAC64 +#include "isaac64.h" +#endif + + +#define ind(mm,x) (*(ub8 *)((ub1 *)(mm) + ((x) & ((RANDSIZ-1)<<3)))) +#define rngstep(mix,a,b,mm,m,m2,r,x) \ +{ \ + x = *m; \ + a = (mix) + *(m2++); \ + *(m++) = y = ind(mm,x) + a + b; \ + *(r++) = b = ind(mm,y>>RANDSIZL) + x; \ +} + +void isaac64(rand64ctx *ctx) +{ + register ub8 a,b,x,y,*m,*mm,*m2,*r,*mend; + mm=ctx->mm; r=ctx->randrsl; + a = ctx->aa; b = ctx->bb + (++ctx->cc); + for (m = mm, mend = m2 = m+(RANDSIZ/2); m>5) , a, b, mm, m, m2, r, x); + rngstep( a^(a<<12) , a, b, mm, m, m2, r, x); + rngstep( a^(a>>33) , a, b, mm, m, m2, r, x); + } + for (m2 = mm; m2>5) , a, b, mm, m, m2, r, x); + rngstep( a^(a<<12) , a, b, mm, m, m2, r, x); + rngstep( a^(a>>33) , a, b, mm, m, m2, r, x); + } + ctx->bb = b; ctx->aa = a; +} + +#define mix(a,b,c,d,e,f,g,h) \ +{ \ + a-=e; f^=h>>9; h+=a; \ + b-=f; g^=a<<9; a+=b; \ + c-=g; h^=b>>23; b+=c; \ + d-=h; a^=c<<15; c+=d; \ + e-=a; b^=d>>14; d+=e; \ + f-=b; c^=e<<20; e+=f; \ + g-=c; d^=f>>17; f+=g; \ + h-=d; e^=g<<14; g+=h; \ +} + +void rand64init(rand64ctx *ctx, word flag) +{ + word i; + ub8 a,b,c,d,e,f,g,h; + ub8 *mm, *randrsl; + ctx->aa = ctx->bb = ctx->cc = (ub8)0; + mm=ctx->mm; + randrsl=ctx->randrsl; + a=b=c=d=e=f=g=h=0x9e3779b97f4a7c13LL; /* the golden ratio */ + + for (i=0; i<4; ++i) /* scramble it */ + { + mix(a,b,c,d,e,f,g,h); + } + + for (i=0; irandcnt=RANDSIZ; /* prepare to use the first set of results */ +} + +#ifdef NEVER +int main() +{ + ub8 i,j; + rand64ctx ctx; + ctx.aa=ctx.bb=ctx.cc=(ub8)0; + for (i=0; i>32),(ub4)ctx.randrsl[j]); + if ((j&3)==3) printf("\n"); + } + } +} +#endif diff --git a/src/isaac_rand/isaac64.h b/src/isaac_rand/isaac64.h new file mode 100644 index 0000000..e2ab55b --- /dev/null +++ b/src/isaac_rand/isaac64.h @@ -0,0 +1,41 @@ +/* +------------------------------------------------------------------------------ +isaac64.h: definitions for a random number generator +Bob Jenkins, 1996, Public Domain +------------------------------------------------------------------------------ +*/ +#ifndef ISAAC64 +#define ISAAC64 + +#include "isaac_standard.h" + +struct rand64ctx +{ + ub8 randrsl[RANDSIZ], randcnt; + ub8 mm[RANDSIZ]; + ub8 aa, bb, cc; +}; +typedef struct rand64ctx rand64ctx; + +/* +------------------------------------------------------------------------------ + If (flag==TRUE), then use the contents of randrsl[0..255] as the seed. +------------------------------------------------------------------------------ +*/ +void rand64init(rand64ctx *r, word flag); + +void isaac64(rand64ctx *ctx); + + +/* +------------------------------------------------------------------------------ + Call rand64() to retrieve a single 64-bit random value +------------------------------------------------------------------------------ +*/ +#define isaac64_rand() \ + (!(r)->randcnt-- ? \ + (isaac64(r), (r)->randcnt=RANDSIZ-1, (r)->randrsl[(r)->>randcnt]) : \ + (r)->randrsl[(r)->randcnt]) + +#endif /* ISAAC64 */ + diff --git a/src/isaac_rand/isaac_rand.h b/src/isaac_rand/isaac_rand.h index 21accbf..167a2fd 100644 --- a/src/isaac_rand/isaac_rand.h +++ b/src/isaac_rand/isaac_rand.h @@ -10,14 +10,10 @@ MODIFIED: 010626: note this is public domain ------------------------------------------------------------------------------ */ -#ifndef STANDARD -#include "isaac_standard.h" -#endif - #ifndef RAND #define RAND -#define RANDSIZL (4) /* I recommend 8 for crypto, 4 for simulations */ -#define RANDSIZ (1<= 8 ) ? &nwipe_isaac64 : &nwipe_isaac; nwipe_options.rounds = 1; nwipe_options.noblank = 0; nwipe_options.nousb = 0; diff --git a/src/prng.c b/src/prng.c index cbf7f67..72c9305 100644 --- a/src/prng.c +++ b/src/prng.c @@ -24,31 +24,49 @@ #include "mt19937ar-cok/mt19937ar-cok.h" #include "isaac_rand/isaac_rand.h" +#include "isaac_rand/isaac64.h" nwipe_prng_t nwipe_twister = { "Mersenne Twister (mt19937ar-cok)", nwipe_twister_init, nwipe_twister_read }; nwipe_prng_t nwipe_isaac = { "ISAAC (rand.c 20010626)", nwipe_isaac_init, nwipe_isaac_read }; +nwipe_prng_t nwipe_isaac64 = { "ISAAC-64 (isaac64.c)", nwipe_isaac64_init, nwipe_isaac64_read }; -int nwipe_u32tobuffer( u8* buffer, u32 rand, int len ) +/* Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian. */ +static inline void u32_to_buffer( u8* restrict buffer, u32 val, const int len ) { - /* - * Print given number of bytes from unsigned integer number to a byte stream buffer starting with low-endian. - */ - int i; - u8 c; // single char - if( len > sizeof( u32 ) ) + for( int i = 0; i < len; ++i ) { - nwipe_log( NWIPE_LOG_FATAL, "Tried to print longer number than the value passed." ); - len = sizeof( u32 ); + buffer[i] = ( u8 )( val & 0xFFUL ); + val >>= 8; } - - for( i = 0; i < len; i++ ) +} +static inline void u64_to_buffer( u8* restrict buffer, u64 val, const int len ) +{ + for( int i = 0; i < len; ++i ) { - c = rand & 0xFFUL; - rand = rand >> 8; - buffer[i] = c; + buffer[i] = ( u8 )( val & 0xFFULL ); + val >>= 8; } - return 0; +} +static inline u32 isaac_nextval( randctx* restrict ctx ) +{ + if( ctx->randcnt == 0 ) + { + isaac( ctx ); + ctx->randcnt = RANDSIZ; + } + ctx->randcnt--; + return ctx->randrsl[ctx->randcnt]; +} +static inline u64 isaac64_nextval( rand64ctx* restrict ctx ) +{ + if( ctx->randcnt == 0 ) + { + isaac64( ctx ); + ctx->randcnt = RANDSIZ; + } + ctx->randcnt--; + return ctx->randrsl[ctx->randcnt]; } int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE ) @@ -66,23 +84,22 @@ int nwipe_twister_init( NWIPE_PRNG_INIT_SIGNATURE ) int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE ) { - u32 i = 0; - u32 ii; - u32 words = count / SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes - u32 remain = count % SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes + u8* restrict bufpos = buffer; + size_t words = count / SIZE_OF_TWISTER; // the values of twister_genrand_int32 is strictly 4 bytes /* Twister returns 4-bytes per call, so progress by 4 bytes. */ - for( ii = 0; ii < words; ++ii ) + for( size_t ii = 0; ii < words; ++ii ) { - nwipe_u32tobuffer( (u8*) ( buffer + i ), twister_genrand_int32( (twister_state_t*) *state ), SIZE_OF_TWISTER ); - i = i + SIZE_OF_TWISTER; + u32_to_buffer( bufpos, twister_genrand_int32( (twister_state_t*) *state ), SIZE_OF_TWISTER ); + bufpos += SIZE_OF_TWISTER; } /* If there is some remainder copy only relevant number of bytes to not * overflow the buffer. */ + const size_t remain = count % SIZE_OF_TWISTER; // SIZE_OF_TWISTER is strictly 4 bytes if( remain > 0 ) { - nwipe_u32tobuffer( (u8*) ( buffer + i ), twister_genrand_int32( (twister_state_t*) *state ), remain ); + u32_to_buffer( bufpos, twister_genrand_int32( (twister_state_t*) *state ), remain ); } return 0; @@ -140,30 +157,95 @@ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE ) int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE ) { - u32 i = 0; - u32 ii; - u32 words = count / SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes - u32 remain = count % SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes - randctx* isaac_state = *state; + u8* restrict bufpos = buffer; + size_t words = count / SIZE_OF_ISAAC; // the values of isaac is strictly 4 bytes /* Isaac returns 4-bytes per call, so progress by 4 bytes. */ - for( ii = 0; ii < words; ++ii ) + for( size_t ii = 0; ii < words; ++ii ) { /* get the next 32bit random number */ - isaac( isaac_state ); - - nwipe_u32tobuffer( (u8*) ( buffer + i ), isaac_state->randrsl[0], SIZE_OF_ISAAC ); - i = i + SIZE_OF_ISAAC; + u32_to_buffer( bufpos, isaac_nextval( isaac_state ), SIZE_OF_ISAAC ); + bufpos += SIZE_OF_ISAAC; } /* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */ + const size_t remain = count % SIZE_OF_ISAAC; // SIZE_OF_ISAAC is strictly 4 bytes if( remain > 0 ) { - /* get the next 32bit random number */ - isaac( isaac_state ); - - nwipe_u32tobuffer( (u8*) ( buffer + i ), isaac_state->randrsl[0], SIZE_OF_ISAAC ); + u32_to_buffer( bufpos, isaac_nextval( isaac_state ), remain ); + } + + return 0; +} + +int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE ) +{ + int count; + rand64ctx* isaac_state = *state; + + nwipe_log( NWIPE_LOG_NOTICE, "Initialising ISAAC-64 prng" ); + + if( *state == NULL ) + { + /* This is the first time that we have been called. */ + *state = malloc( sizeof( rand64ctx ) ); + isaac_state = *state; + + /* Check the memory allocation. */ + if( isaac_state == 0 ) + { + nwipe_perror( errno, __FUNCTION__, "malloc" ); + nwipe_log( NWIPE_LOG_FATAL, "Unable to allocate memory for the isaac state." ); + return -1; + } + } + + /* Take the minimum of the isaac seed size and available entropy. */ + if( sizeof( isaac_state->randrsl ) < seed->length ) + { + count = sizeof( isaac_state->randrsl ); + } + else + { + memset( isaac_state->randrsl, 0, sizeof( isaac_state->randrsl ) ); + count = seed->length; + } + + if( count == 0 ) + { + /* Start ISACC without a seed. */ + rand64init( isaac_state, 0 ); + } + else + { + /* Seed the ISAAC state with entropy. */ + memcpy( isaac_state->randrsl, seed->s, count ); + + /* The second parameter indicates that randrsl is non-empty. */ + rand64init( isaac_state, 1 ); + } + + return 0; +} + +int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE ) +{ + rand64ctx* isaac_state = *state; + u8* restrict bufpos = buffer; + size_t words = count / SIZE_OF_ISAAC64; // the values of ISAAC-64 is strictly 8 bytes + + for( size_t ii = 0; ii < words; ++ii ) + { + u64_to_buffer( bufpos, isaac64_nextval( isaac_state ), SIZE_OF_ISAAC64 ); + bufpos += SIZE_OF_ISAAC64; + } + + /* If there is some remainder copy only relevant number of bytes to not overflow the buffer. */ + const size_t remain = count % SIZE_OF_ISAAC64; // SIZE_OF_ISAAC64 is strictly 8 bytes + if( remain > 0 ) + { + u64_to_buffer( bufpos, isaac64_nextval( isaac_state ), remain ); } return 0; diff --git a/src/prng.h b/src/prng.h index 8b03f5a..8dfa3d7 100644 --- a/src/prng.h +++ b/src/prng.h @@ -52,11 +52,14 @@ int nwipe_twister_read( NWIPE_PRNG_READ_SIGNATURE ); /* ISAAC prototypes. */ int nwipe_isaac_init( NWIPE_PRNG_INIT_SIGNATURE ); int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE ); +int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE ); +int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE ); /* Size of the twister is not derived from the architecture, but it is strictly 4 bytes */ #define SIZE_OF_TWISTER 4 -/* Size of the isaac is not derived from the architecture, but it is strictly 4 bytes */ +/* Size of the isaac/isaac64 is not derived from the architecture, but it is strictly 4 or 8 bytes */ #define SIZE_OF_ISAAC 4 +#define SIZE_OF_ISAAC64 8 #endif /* PRNG_H_ */