From 9acd2c86e00cbb8a1745296a47f57de9588cef57 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 13 May 2024 14:02:30 +0200 Subject: Merging upstream version 0.37. Signed-off-by: Daniel Baumann --- src/Makefile.am | 2 +- src/alfg/add_lagg_fibonacci_prng.c | 79 +++++++++++++++++++++ src/alfg/add_lagg_fibonacci_prng.h | 43 ++++++++++++ src/conf.c | 17 ++--- src/create_pdf.c | 18 ++++- src/gui.c | 120 ++++++++++++++++++++++++++++++- src/hpa_dco.c | 3 + src/mt19937ar-cok/mt19937ar-cok.c | 140 +++++++++++++++++++++---------------- src/mt19937ar-cok/mt19937ar-cok.h | 25 ++++--- src/options.c | 53 +++++++++++--- src/pass.c | 2 +- src/prng.c | 91 ++++++++++++++++++++++++ src/prng.h | 14 ++++ src/temperature.c | 4 +- src/version.c | 4 +- src/xor/xoroshiro256_prng.c | 74 ++++++++++++++++++++ src/xor/xoroshiro256_prng.h | 44 ++++++++++++ 17 files changed, 630 insertions(+), 103 deletions(-) create mode 100644 src/alfg/add_lagg_fibonacci_prng.c create mode 100644 src/alfg/add_lagg_fibonacci_prng.h create mode 100644 src/xor/xoroshiro256_prng.c create mode 100644 src/xor/xoroshiro256_prng.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 7d9bb44..ac652c9 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 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 PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.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 alfg/add_lagg_fibonacci_prng.h alfg/add_lagg_fibonacci_prng.c xor/xoroshiro256_prng.h xor/xoroshiro256_prng.c pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG) diff --git a/src/alfg/add_lagg_fibonacci_prng.c b/src/alfg/add_lagg_fibonacci_prng.c new file mode 100644 index 0000000..e84f90e --- /dev/null +++ b/src/alfg/add_lagg_fibonacci_prng.c @@ -0,0 +1,79 @@ +/* + * Additive Lagged Fibonacci Generator (ALFG) Implementation + * Author: Fabian Druschke + * Date: 2024-03-13 + * + * This is an implementation of the Additive Lagged Fibonacci Generator (ALFG), + * a pseudorandom number generator known for its simplicity and good statistical properties + * for a wide range of applications. ALFGs are particularly noted for their long periods + * and efficiency in generating sequences of random numbers. However, like many other PRNGs, + * they are not suitable for cryptographic purposes due to their predictability. + * + * As the author of this implementation, I, Fabian Druschke, hereby release this work into + * the public domain. I dedicate any and all copyright interest in this work to the public + * domain, making it free to use for anyone for any purpose without any conditions, unless + * such conditions are required by law. + * + * This software is provided "as is", without warranty of any kind, express or implied, + * including but not limited to the warranties of merchantability, fitness for a particular + * purpose, and noninfringement. In no event shall the authors be liable for any claim, + * damages, or other liability, whether in an action of contract, tort, or otherwise, arising + * from, out of, or in connection with the software or the use or other dealings in the software. + * + * Note: This implementation is designed for non-cryptographic applications and should not be + * used where cryptographic security is required. + */ + +#include "add_lagg_fibonacci_prng.h" +#include +#include + +#define STATE_SIZE 64 // Size of the state array, sufficient for a high period +#define LAG_BIG 55 // Large lag, e.g., 55 +#define LAG_SMALL 24 // Small lag, e.g., 24 +#define MODULUS ( 1ULL << 48 ) // Modulus for the operations, here 2^48 for simple handling + +void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length ) +{ + // Simple initialization: Fill the state with the key values and then with a linear combination of them + for( unsigned long i = 0; i < STATE_SIZE; i++ ) + { + if( i < key_length ) + { + state->s[i] = init_key[i]; + } + else + { + // Simple method to generate further state values. Should be improved for serious applications. + state->s[i] = ( 6364136223846793005ULL * state->s[i - 1] + 1 ) % MODULUS; + } + } + state->index = 0; // Initialize the index for the first generation +} + +void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos ) +{ + uint64_t* buf_as_uint64 = (uint64_t*) bufpos; // Interprets bufpos as a uint64_t array for direct assignment + int64_t result; // Use signed integer to handle potential negative results from subtraction + + for (int i = 0; i < 4; i++) { + // Subtract the two previous numbers in the sequence + result = (int64_t)state->s[(state->index + LAG_BIG) % STATE_SIZE] - (int64_t)state->s[(state->index + LAG_SMALL) % STATE_SIZE]; + + // Handle borrow if result is negative + if (result < 0) { + result += MODULUS; + // Optionally set a borrow flag or adjust the next operation based on borrow logic + } + + // Store the result (after adjustment) back into the state, ensuring it's positive and within range + state->s[state->index] = (uint64_t)result; + + // Write the result into buf_as_uint64 + buf_as_uint64[i] = state->s[state->index]; + + // Update the index for the next round + state->index = (state->index + 1) % STATE_SIZE; + } +} + diff --git a/src/alfg/add_lagg_fibonacci_prng.h b/src/alfg/add_lagg_fibonacci_prng.h new file mode 100644 index 0000000..eed42d1 --- /dev/null +++ b/src/alfg/add_lagg_fibonacci_prng.h @@ -0,0 +1,43 @@ +/* + * Additive Lagged Fibonacci Generator (ALFG) Implementation definitions + * Author: Fabian Druschke + * Date: 2024-03-13 + * + * This is an implementation of the Additive Lagged Fibonacci Generator (ALFG), + * a pseudorandom number generator known for its simplicity and good statistical properties + * for a wide range of applications. ALFGs are particularly noted for their long periods + * and efficiency in generating sequences of random numbers. However, like many other PRNGs, + * they are not suitable for cryptographic purposes due to their predictability. + * + * As the author of this implementation, I, Fabian Druschke, hereby release this work into + * the public domain. I dedicate any and all copyright interest in this work to the public + * domain, making it free to use for anyone for any purpose without any conditions, unless + * such conditions are required by law. + * + * This software is provided "as is", without warranty of any kind, express or implied, + * including but not limited to the warranties of merchantability, fitness for a particular + * purpose, and noninfringement. In no event shall the authors be liable for any claim, + * damages, or other liability, whether in an action of contract, tort, or otherwise, arising + * from, out of, or in connection with the software or the use or other dealings in the software. + * + * Note: This implementation is designed for non-cryptographic applications and should not be + * used where cryptographic security is required. + */ + +#ifndef ADD_LAGG_FIBONACCI_PRNG_H +#define ADD_LAGG_FIBONACCI_PRNG_H + +#include + +// State definition for the Additive Lagged Fibonacci Generator +typedef struct +{ + uint64_t s[64]; // State array + unsigned int index; // Current index in the state array +} add_lagg_fibonacci_state_t; + +// Function prototypes +void add_lagg_fibonacci_init( add_lagg_fibonacci_state_t* state, uint64_t init_key[], unsigned long key_length ); +void add_lagg_fibonacci_genrand_uint256_to_buf( add_lagg_fibonacci_state_t* state, unsigned char* bufpos ); + +#endif // ADD_LAGG_FIBONACCI_PRNG_H diff --git a/src/conf.c b/src/conf.c index 13deffa..e0dcdcd 100644 --- a/src/conf.c +++ b/src/conf.c @@ -392,11 +392,12 @@ int nwipe_conf_update_setting( char* group_name_setting_name, char* setting_valu int nwipe_conf_read_setting( char* group_name_setting_name, const char** setting_value ) { - /* You would call this function if you wanted to read a settings value in nwipe.conf, i.e + /* This function returns a setting value from nwipe's configuration file nwipe.conf + * when provided with a groupname.settingname string. * + * Example: * const char ** pReturnString; * nwipe_conf_read_setting( "PDF_Certificate", "PDF_Enable", pReturnString ); - * */ /* Separate group_name_setting_name i.e "PDF_Certificate.PDF_Enable" string @@ -406,20 +407,20 @@ int nwipe_conf_read_setting( char* group_name_setting_name, const char** setting int return_status; int length = strlen( group_name_setting_name ); - char* group_name = malloc( length ); - char* setting_name = malloc( length ); + char* group_name = calloc( length, sizeof( char ) ); + char* setting_name = calloc( length, sizeof( char ) ); int idx = 0; while( group_name_setting_name[idx] != 0 && group_name_setting_name[idx] != '.' ) { - if( group_name_setting_name[idx] == '.' ) - { - break; - } idx++; } + // Copy the group name from the combined input string memcpy( group_name, group_name_setting_name, idx ); + group_name[idx] = '\0'; // Null-terminate group_name + + // Copy the setting name from the combined input string strcpy( setting_name, &group_name_setting_name[idx + 1] ); if( !( setting = config_lookup( &nwipe_cfg, group_name ) ) ) diff --git a/src/create_pdf.c b/src/create_pdf.c index 754543b..b732ed7 100644 --- a/src/create_pdf.c +++ b/src/create_pdf.c @@ -63,6 +63,8 @@ int create_pdf( nwipe_context_t* ptr ) extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; extern nwipe_prng_t nwipe_isaac64; + extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng; + extern nwipe_prng_t nwipe_xoroshiro256_prng; /* Used by libconfig functions to retrieve data from nwipe.conf defined in conf.c */ extern config_t nwipe_cfg; @@ -466,7 +468,21 @@ int create_pdf( nwipe_context_t* ptr ) } else { - snprintf( prng_type, sizeof( prng_type ), "Unknown" ); + if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng ) + { + snprintf( prng_type, sizeof( prng_type ), "Fibonacci" ); + } + else + { + if( nwipe_options.prng == &nwipe_xoroshiro256_prng ) + { + snprintf( prng_type, sizeof( prng_type ), "XORshiro256" ); + } + else + { + snprintf( prng_type, sizeof( prng_type ), "Unknown" ); + } + } } } } diff --git a/src/gui.c b/src/gui.c index 9c34910..03776b6 100644 --- a/src/gui.c +++ b/src/gui.c @@ -1599,10 +1599,14 @@ void nwipe_gui_prng( void ) extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; extern nwipe_prng_t nwipe_isaac64; + extern nwipe_prng_t nwipe_aes_ctr_prng; + extern nwipe_prng_t nwipe_xoroshiro256_prng; + extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng; + extern int terminate_signal; /* The number of implemented PRNGs. */ - const int count = 3; + const int count = 5; /* The first tabstop. */ const int tab1 = 2; @@ -1636,7 +1640,14 @@ void nwipe_gui_prng( void ) { focus = 2; } - + if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng ) + { + focus = 3; + } + if( nwipe_options.prng == &nwipe_xoroshiro256_prng ) + { + focus = 4; + } do { /* Clear the main window. */ @@ -1651,6 +1662,8 @@ void nwipe_gui_prng( void ) 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, " %s", nwipe_add_lagg_fibonacci_prng.label ); + mvwprintw( main_window, yy++, tab1, " %s", nwipe_xoroshiro256_prng.label ); yy++; /* Print the cursor. */ @@ -1734,7 +1747,100 @@ void nwipe_gui_prng( void ) "Performs best on a 64-bit CPU. Use ISAAC if this system has a 32-bit CPU. " ); break; - } /* switch */ + case 3: + + mvwprintw( main_window, + yy++, + tab1, + "ALFG (Additive Lagged Fibonacci Generator), is a class of PRNGs utilizing" ); + mvwprintw( main_window, + yy++, + tab1, + "the Fibonacci sequence with additive operations between lagged values. While" ); + mvwprintw( main_window, + yy++, + tab1, + "they offer a good balance between speed and randomness, it's important to note" ); + mvwprintw( main_window, + yy++, + tab1, + "that they provide lower levels of security, making them less suitable for" ); + mvwprintw( main_window, + yy++, + tab1, + "cryptographic applications. Their periodicity depends on the choice of lags" ); + mvwprintw( main_window, + yy++, + tab1, + "and arithmetic operations, potentially achieving large values, often 2^N or" ); + mvwprintw( main_window, + yy++, + tab1, + "higher, where N is the bit length of the states. " ); + mvwprintw( main_window, + yy++, + tab1, + " " ); + mvwprintw( main_window, + yy++, + tab1, + "Efficient on CPUs of any bit width, particularly suited for non-cryptographic" ); + mvwprintw( main_window, + yy++, + tab1, + "applications requiring long sequences with a good speed-randomness trade-off. " ); + break; + + case 4: + + mvwprintw( main_window, + yy++, + tab1, + "Xoroshiro256**, originally designed by David Blackman and Sebastiano Vigna" ); + mvwprintw( main_window, + yy++, + tab1, + "for 128 bits, was adapted to 256 bits by Fabian Druschke. This adaptation " ); + mvwprintw( main_window, + yy++, + tab1, + "enhances its capability for fast, high-quality generation of pseudo-random " ); + mvwprintw( main_window, + yy++, + tab1, + "numbers with a state size of 256 bits. It boasts an extremely long period " ); + mvwprintw( main_window, + yy++, + tab1, + "of 2^256-1 without sacrificing performance, suitable for a wide range of " ); + mvwprintw( main_window, + yy++, + tab1, + "applications. " ); + mvwprintw( main_window, + yy++, + tab1, + " " ); + mvwprintw( main_window, + yy++, + tab1, + "The simple arithmetic operations (shifts, rotations, and XORs) of " ); + mvwprintw( main_window, + yy++, + tab1, + "Xoroshiro256** ensure low computational complexity. This, combined with " ); + mvwprintw( main_window, + yy++, + tab1, + "the adaptation for 256 bits by Fabian Druschke, allows efficient use " ); + mvwprintw( main_window, + yy++, + tab1, + "especially for legacy systems, due to its efficiency and minimal demands. " ); + break; + } + + /* switch */ /* Add a border. */ box( main_window, 0, 0 ); @@ -1794,6 +1900,14 @@ void nwipe_gui_prng( void ) { nwipe_options.prng = &nwipe_isaac64; } + if( focus == 3 ) + { + nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng; + } + if( focus == 4 ) + { + nwipe_options.prng = &nwipe_xoroshiro256_prng; + } return; case KEY_BACKSPACE: diff --git a/src/hpa_dco.c b/src/hpa_dco.c index 160d454..bbd3d1c 100644 --- a/src/hpa_dco.c +++ b/src/hpa_dco.c @@ -722,6 +722,9 @@ u64 nwipe_read_dco_real_max_sectors( char* device ) unsigned char buffer[LBA_SIZE]; // Received data block unsigned char sense_buffer[SENSE_BUFFER_SIZE]; // Sense data + /* Zero the data block prior to use */ + memset( buffer, 0, LBA_SIZE ); + /* three characters represent one byte of sense data, i.e * two characters and a space "01 AE 67" */ diff --git a/src/mt19937ar-cok/mt19937ar-cok.c b/src/mt19937ar-cok/mt19937ar-cok.c index 63ef659..af8cc75 100644 --- a/src/mt19937ar-cok/mt19937ar-cok.c +++ b/src/mt19937ar-cok/mt19937ar-cok.c @@ -1,16 +1,16 @@ -/* - This code is modified for use in nwipe. +/* + This code is modified for use in nwipe. A C-program for MT19937, with initialization improved 2002/2/10. Coded by Takuji Nishimura and Makoto Matsumoto. This is a faster version by taking Shawn Cokus's optimization, Matthe Bellew's simplification, Isaku Wada's real version. - Before using, initialize the state by using init_genrand(seed) + Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. + All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -23,8 +23,8 @@ notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -48,77 +48,89 @@ #include #include "mt19937ar-cok.h" -/* initializes state[N] with a seed */ -void init_genrand( twister_state_t* state, unsigned long s) +/* initializes state[MT_STATE_SIZE] with a seed */ +void init_genrand( twister_state_t* state, unsigned long s ) { - int j; - state->array[0]= s & 0xffffffffUL; - for( j = 1; j < N; j++ ) - { - state->array[j] = (1812433253UL * (state->array[j-1] ^ (state->array[j-1] >> 30)) + j); - state->array[j] &= 0xffffffffUL; /* for >32 bit machines */ - } - state->left = 1; - state->initf = 1; + int j; + state->array[0] = s & 0xffffffffUL; + for( j = 1; j < MT_STATE_SIZE; j++ ) + { + state->array[j] = ( 1812433253UL * ( state->array[j - 1] ^ ( state->array[j - 1] >> 30 ) ) + j ); + state->array[j] &= 0xffffffffUL; /* for >32 bit machines */ + } + state->left = 1; + state->initf = 1; } - void twister_init( twister_state_t* state, unsigned long init_key[], unsigned long key_length ) { int i = 1; - int j = 0; - int k = ( N > key_length ? N : key_length ); + int j = 0; + int k = ( MT_STATE_SIZE > key_length ? MT_STATE_SIZE : key_length ); init_genrand( state, 19650218UL ); for( ; k; k-- ) - { - state->array[i] = (state->array[i] ^ ((state->array[i-1] ^ (state->array[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; - state->array[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - ++i; - ++j; - - if ( i >= N ) - { - state->array[0] = state->array[N-1]; - i = 1; - } - - if ( j >= key_length ) - { - j = 0; - } + { + state->array[i] = ( state->array[i] ^ ( ( state->array[i - 1] ^ ( state->array[i - 1] >> 30 ) ) * 1664525UL ) ) + + init_key[j] + j; + state->array[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + ++i; + ++j; + + if( i >= MT_STATE_SIZE ) + { + state->array[0] = state->array[MT_STATE_SIZE - 1]; + i = 1; + } + + if( j >= key_length ) + { + j = 0; + } } - for( k = N -1; k; k-- ) - { - state->array[i] = (state->array[i] ^ ((state->array[i-1] ^ (state->array[i-1] >> 30)) * 1566083941UL)) - i; - state->array[i] &= 0xffffffffUL; - ++i; - - if ( i >= N ) - { - state->array[0] = state->array[N-1]; - i = 1; - } + for( k = MT_STATE_SIZE - 1; k; k-- ) + { + state->array[i] = + ( state->array[i] ^ ( ( state->array[i - 1] ^ ( state->array[i - 1] >> 30 ) ) * 1566083941UL ) ) - i; + state->array[i] &= 0xffffffffUL; + ++i; + + if( i >= MT_STATE_SIZE ) + { + state->array[0] = state->array[MT_STATE_SIZE - 1]; + i = 1; + } } - state->array[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ - state->left = 1; - state->initf = 1; + state->array[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ + state->left = 1; + state->initf = 1; } static void next_state( twister_state_t* state ) { - unsigned long *p = state->array; + unsigned long* p = state->array; int j; - if( state->initf == 0) { init_genrand( state, 5489UL ); } - state->left = N; + // Ensures the generator is initialized + if( state->initf == 0 ) + { + init_genrand( state, 5489UL ); + } + state->left = MT_STATE_SIZE; state->next = state->array; - for( j = N - M + 1; --j; p++ ) { *p = p[M] ^ TWIST(p[0], p[1]); } - for( j = M; --j; p++ ) { *p = p[M-N] ^ TWIST(p[0], p[1]); } - *p = p[M-N] ^ TWIST(p[0], state->array[0]); + + for( j = MT_STATE_SIZE - MT_MIDDLE_WORD + 1; --j; p++ ) + { + *p = p[MT_MIDDLE_WORD] ^ TWIST( p[0], p[1] ); + } + for( j = MT_MIDDLE_WORD; --j; p++ ) + { + *p = p[MT_MIDDLE_WORD - MT_STATE_SIZE] ^ TWIST( p[0], p[1] ); + } + *p = p[MT_MIDDLE_WORD - MT_STATE_SIZE] ^ TWIST( p[0], state->array[0] ); } /* generates a random number on [0,0xffffffff]-interval */ @@ -126,14 +138,18 @@ unsigned long twister_genrand_int32( twister_state_t* state ) { unsigned long y; - if ( --state->left == 0 ) { next_state( state ); } + // Advance internal state if necessary + if( --state->left == 0 ) + { + next_state( state ); + } y = *state->next++; - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); + // Tempering + y ^= ( y >> 11 ); + y ^= ( y << 7 ) & 0x9d2c5680UL; + y ^= ( y << 15 ) & 0xefc60000UL; + y ^= ( y >> 18 ); return y; } diff --git a/src/mt19937ar-cok/mt19937ar-cok.h b/src/mt19937ar-cok/mt19937ar-cok.h index afcc873..202a0f5 100644 --- a/src/mt19937ar-cok/mt19937ar-cok.h +++ b/src/mt19937ar-cok/mt19937ar-cok.h @@ -1,30 +1,29 @@ /* - * mt19937ar-cok.h: The Mersenne Twister PRNG implementation for nwipe. - * + * mt19937ar-cok.h: The Mersenne Twister PRNG implementation for nwipe. */ #ifndef MT19937AR_H_ #define MT19937AR_H_ /* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define MT_STATE_SIZE 624 +#define MT_MIDDLE_WORD 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UMASK 0x80000000UL /* most significant w-r bits */ #define LMASK 0x7fffffffUL /* least significant r bits */ -#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) -#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) +#define MIXBITS( u, v ) ( ( (u) &UMASK ) | ( (v) &LMASK ) ) +#define TWIST( u, v ) ( ( MIXBITS( u, v ) >> 1 ) ^ ( (v) &1UL ? MATRIX_A : 0UL ) ) typedef struct twister_state_t_ { - unsigned long array[N]; - int left; - int initf; - unsigned long *next; -} twister_state_t; + unsigned long array[MT_STATE_SIZE]; // Updated to use MT_STATE_SIZE + int left; + int initf; + unsigned long* next; +} twister_state_t; /* Initialize the MT state. ( 0 < key_length <= 624 ). */ -void twister_init( twister_state_t* state, unsigned long init_key[], unsigned long key_length); +void twister_init( twister_state_t* state, unsigned long init_key[], unsigned long key_length ); /* Generate a random integer on the [0,0xffffffff] interval. */ unsigned long twister_genrand_int32( twister_state_t* state ); diff --git a/src/options.c b/src/options.c index 95050db..c855d0e 100644 --- a/src/options.c +++ b/src/options.c @@ -42,6 +42,8 @@ int nwipe_options_parse( int argc, char** argv ) extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; extern nwipe_prng_t nwipe_isaac64; + extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng; + extern nwipe_prng_t nwipe_xoroshiro256_prng; /* The getopt() result holder. */ int nwipe_opt; @@ -127,8 +129,9 @@ int nwipe_options_parse( int argc, char** argv ) /* Set default options. */ nwipe_options.autonuke = 0; nwipe_options.autopoweroff = 0; - nwipe_options.method = &nwipe_dodshort; - nwipe_options.prng = ( sizeof( unsigned long int ) >= 8 ) ? &nwipe_isaac64 : &nwipe_isaac; + nwipe_options.method = &nwipe_random; + nwipe_options.prng = + ( sizeof( unsigned long int ) >= 8 ) ? &nwipe_xoroshiro256_prng : &nwipe_add_lagg_fibonacci_prng; nwipe_options.rounds = 1; nwipe_options.noblank = 0; nwipe_options.nousb = 0; @@ -490,6 +493,16 @@ int nwipe_options_parse( int argc, char** argv ) nwipe_options.prng = &nwipe_isaac64; break; } + if( strcmp( optarg, "add_lagg_fibonacci_prng" ) == 0 ) + { + nwipe_options.prng = &nwipe_add_lagg_fibonacci_prng; + break; + } + if( strcmp( optarg, "xoroshiro256_prng" ) == 0 ) + { + nwipe_options.prng = &nwipe_xoroshiro256_prng; + break; + } /* Else we do not know this PRNG. */ fprintf( stderr, "Error: Unknown prng '%s'.\n", optarg ); @@ -539,6 +552,8 @@ void nwipe_options_log( void ) extern nwipe_prng_t nwipe_twister; extern nwipe_prng_t nwipe_isaac; extern nwipe_prng_t nwipe_isaac64; + extern nwipe_prng_t nwipe_add_lagg_fibonacci_prng; + extern nwipe_prng_t nwipe_xoroshiro256_prng; /** * Prints a manifest of options to the log. @@ -592,19 +607,33 @@ void nwipe_options_log( void ) } else { - if( nwipe_options.prng == &nwipe_isaac ) + if( nwipe_options.prng == &nwipe_add_lagg_fibonacci_prng ) { - nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" ); + nwipe_log( NWIPE_LOG_NOTICE, " prng = Lagged Fibonacci generator (EXPERIMENTAL!)" ); } else { - if( nwipe_options.prng == &nwipe_isaac64 ) + if( nwipe_options.prng == &nwipe_xoroshiro256_prng ) { - nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac64" ); + nwipe_log( NWIPE_LOG_NOTICE, " prng = XORoshiro-256 (EXPERIMENTAL!)" ); } else { - nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" ); + if( nwipe_options.prng == &nwipe_isaac ) + { + nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac" ); + } + else + { + if( nwipe_options.prng == &nwipe_isaac64 ) + { + nwipe_log( NWIPE_LOG_NOTICE, " prng = Isaac64" ); + } + else + { + nwipe_log( NWIPE_LOG_NOTICE, " prng = Undefined" ); + } + } } } } @@ -666,7 +695,10 @@ void display_help() puts( " (default: last)" ); puts( " off - Do not verify" ); puts( " last - Verify after the last pass" ); - puts( " all - Verify every pass\n" ); + puts( " all - Verify every pass" ); + puts( " " ); + puts( " Please mind that HMG IS5 enhanced always verifies the" ); + puts( " last (PRNG) pass regardless of this option.\n" ); puts( " -m, --method=METHOD The wiping method. See man page for more details." ); puts( " (default: dodshort)" ); puts( " dod522022m / dod - 7 pass DOD 5220.22-M method" ); @@ -677,11 +709,12 @@ void display_help() puts( " zero / quick - Overwrite with zeros" ); puts( " one - Overwrite with ones (0xFF)" ); puts( " verify_zero - Verifies disk is zero filled" ); - puts( " verify_one - Verifies disk is 0xFF filled\n" ); + puts( " verify_one - Verifies disk is 0xFF filled" ); + puts( " is5enh - HMG IS5 enhanced\n" ); puts( " -l, --logfile=FILE Filename to log to. Default is STDOUT\n" ); puts( " -P, --PDFreportpath=PATH Path to write PDF reports to. Default is \".\"" ); puts( " If set to \"noPDF\" no PDF reports are written.\n" ); - puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64)\n" ); + puts( " -p, --prng=METHOD PRNG option (mersenne|twister|isaac|isaac64|add_lagg_fibonacci_prng)\n" ); puts( " -q, --quiet Anonymize logs and the GUI by removing unique data, i.e." ); puts( " serial numbers, LU WWN Device ID, and SMBIOS/DMI data" ); puts( " XXXXXX = S/N exists, ????? = S/N not obtainable\n" ); diff --git a/src/pass.c b/src/pass.c index 9c730da..fc48ac1 100644 --- a/src/pass.c +++ b/src/pass.c @@ -324,7 +324,7 @@ int nwipe_random_pass( NWIPE_METHOD_SIGNATURE ) /* For the first block only, check the prng actually wrote something to the buffer */ if( z == c->device_size ) { - idx = c->device_stat.st_blksize; + idx = c->device_stat.st_blksize - 1; while( idx > 0 ) { if( b[idx] != 0 ) diff --git a/src/prng.c b/src/prng.c index 45c6cb7..eaebabd 100644 --- a/src/prng.c +++ b/src/prng.c @@ -25,12 +25,21 @@ #include "mt19937ar-cok/mt19937ar-cok.h" #include "isaac_rand/isaac_rand.h" #include "isaac_rand/isaac64.h" +#include "alfg/add_lagg_fibonacci_prng.h" //Lagged Fibonacci generator prototype +#include "xor/xoroshiro256_prng.h" //XORoshiro-256 prototype 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 }; +/* ALFG PRNG Structure */ +nwipe_prng_t nwipe_add_lagg_fibonacci_prng = { "Lagged Fibonacci generator", + nwipe_add_lagg_fibonacci_prng_init, + nwipe_add_lagg_fibonacci_prng_read }; +/* XOROSHIRO-256 PRNG Structure */ +nwipe_prng_t nwipe_xoroshiro256_prng = { "XORoshiro-256", nwipe_xoroshiro256_prng_init, nwipe_xoroshiro256_prng_read }; + /* 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 ) { @@ -250,3 +259,85 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE ) return 0; } + +/* EXPERIMENTAL implementation of Lagged Fibonacci generator a lot of random numbers */ +int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE ) +{ + if( *state == NULL ) + { + nwipe_log( NWIPE_LOG_NOTICE, "Initialising Lagged Fibonacci generator PRNG" ); + *state = malloc( sizeof( add_lagg_fibonacci_state_t ) ); + } + add_lagg_fibonacci_init( + (add_lagg_fibonacci_state_t*) *state, (unsigned long*) ( seed->s ), seed->length / sizeof( unsigned long ) ); + + return 0; +} + +/* EXPERIMENTAL implementation of XORoroshiro256 algorithm to provide high-quality, but a lot of random numbers */ +int nwipe_xoroshiro256_prng_init( NWIPE_PRNG_INIT_SIGNATURE ) +{ + nwipe_log( NWIPE_LOG_NOTICE, "Initialising XORoroshiro-256 PRNG" ); + + if( *state == NULL ) + { + /* This is the first time that we have been called. */ + *state = malloc( sizeof( xoroshiro256_state_t ) ); + } + xoroshiro256_init( + (xoroshiro256_state_t*) *state, (unsigned long*) ( seed->s ), seed->length / sizeof( unsigned long ) ); + + return 0; +} + +int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE ) +{ + u8* restrict bufpos = buffer; + size_t words = count / SIZE_OF_ADD_LAGG_FIBONACCI_PRNG; + + /* Loop to fill the buffer with blocks directly from the Fibonacci algorithm */ + for( size_t ii = 0; ii < words; ++ii ) + { + add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, bufpos ); + bufpos += SIZE_OF_ADD_LAGG_FIBONACCI_PRNG; // Move to the next block + } + + /* Handle remaining bytes if count is not a multiple of SIZE_OF_ADD_LAGG_FIBONACCI_PRNG */ + const size_t remain = count % SIZE_OF_ADD_LAGG_FIBONACCI_PRNG; + if( remain > 0 ) + { + unsigned char temp_output[16]; // Temporary buffer for the last block + add_lagg_fibonacci_genrand_uint256_to_buf( (add_lagg_fibonacci_state_t*) *state, temp_output ); + + // Copy the remaining bytes + memcpy( bufpos, temp_output, remain ); + } + + return 0; // Success +} + +int nwipe_xoroshiro256_prng_read( NWIPE_PRNG_READ_SIGNATURE ) +{ + u8* restrict bufpos = buffer; + size_t words = count / SIZE_OF_XOROSHIRO256_PRNG; + + /* Loop to fill the buffer with blocks directly from the XORoroshiro256 algorithm */ + for( size_t ii = 0; ii < words; ++ii ) + { + xoroshiro256_genrand_uint256_to_buf( (xoroshiro256_state_t*) *state, bufpos ); + bufpos += SIZE_OF_XOROSHIRO256_PRNG; // Move to the next block + } + + /* Handle remaining bytes if count is not a multiple of SIZE_OF_XOROSHIRO256_PRNG */ + const size_t remain = count % SIZE_OF_XOROSHIRO256_PRNG; + if( remain > 0 ) + { + unsigned char temp_output[16]; // Temporary buffer for the last block + xoroshiro256_genrand_uint256_to_buf( (xoroshiro256_state_t*) *state, temp_output ); + + // Copy the remaining bytes + memcpy( bufpos, temp_output, remain ); + } + + return 0; // Success +} diff --git a/src/prng.h b/src/prng.h index 8dfa3d7..a9add09 100644 --- a/src/prng.h +++ b/src/prng.h @@ -55,6 +55,14 @@ int nwipe_isaac_read( NWIPE_PRNG_READ_SIGNATURE ); int nwipe_isaac64_init( NWIPE_PRNG_INIT_SIGNATURE ); int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE ); +/* ALFG prototypes. */ +int nwipe_add_lagg_fibonacci_prng_init( NWIPE_PRNG_INIT_SIGNATURE ); +int nwipe_add_lagg_fibonacci_prng_read( NWIPE_PRNG_READ_SIGNATURE ); + +/* XOROSHIRO-256 prototypes. */ +int nwipe_xoroshiro256_prng_init( NWIPE_PRNG_INIT_SIGNATURE ); +int nwipe_xoroshiro256_prng_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 @@ -62,4 +70,10 @@ int nwipe_isaac64_read( NWIPE_PRNG_READ_SIGNATURE ); #define SIZE_OF_ISAAC 4 #define SIZE_OF_ISAAC64 8 +/* Size of the Lagged Fibonacci generator is not derived from the architecture, but it is strictly 32 bytes */ +#define SIZE_OF_ADD_LAGG_FIBONACCI_PRNG 32 + +/* Size of the XOROSHIRO-256 is not derived from the architecture, but it is strictly 32 bytes */ +#define SIZE_OF_XOROSHIRO256_PRNG 32 + #endif /* PRNG_H_ */ diff --git a/src/temperature.c b/src/temperature.c index 19f9446..3f69e7b 100644 --- a/src/temperature.c +++ b/src/temperature.c @@ -16,8 +16,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -//#define _LARGEFILE64_SOURCE -//#define _FILE_OFFSET_BITS 64 +// #define _LARGEFILE64_SOURCE +// #define _FILE_OFFSET_BITS 64 #define _BSD_SOURCE #include diff --git a/src/version.c b/src/version.c index cbaa106..bf00573 100644 --- a/src/version.c +++ b/src/version.c @@ -4,7 +4,7 @@ * used by configure to dynamically assign those values * to documentation files. */ -const char* version_string = "0.36"; +const char* version_string = "0.37"; const char* program_name = "nwipe"; const char* author_name = "Martijn van Brummelen"; const char* email_address = "git@brumit.nl"; @@ -14,4 +14,4 @@ Modifications to original dwipe Copyright Andy Beverley \n\ This is free software; see the source for copying conditions.\n\ There is NO warranty; not even for MERCHANTABILITY or FITNESS\n\ FOR A PARTICULAR PURPOSE.\n"; -const char* banner = "nwipe 0.36"; +const char* banner = "nwipe 0.37"; diff --git a/src/xor/xoroshiro256_prng.c b/src/xor/xoroshiro256_prng.c new file mode 100644 index 0000000..defef88 --- /dev/null +++ b/src/xor/xoroshiro256_prng.c @@ -0,0 +1,74 @@ +/* + * XORoshiro-256 PRNG Implementation + * Author: Fabian Druschke + * Date: 2024-03-13 + * + * This is a XORoshiro-256 (XOR/rotate/shift/rotate) pseudorandom number generator + * implementation, designed for fast and efficient generation of high-quality + * pseudorandom numbers. XORoshiro-256 is part of the XORoshiro family of PRNGs known + * for their simplicity and excellent statistical properties for a wide range of + * applications, though they are not suitable for cryptographic purposes due to their + * predictability. + * + * As the author of this implementation, I, Fabian Druschke, hereby release this work into + * the public domain. I dedicate any and all copyright interest in this work to the public + * domain, making it free to use for anyone for any purpose without any conditions, unless + * such conditions are required by law. + * + * This software is provided "as is", without warranty of any kind, express or implied, + * including but not limited to the warranties of merchantability, fitness for a particular + * purpose, and noninfringement. In no event shall the authors be liable for any claim, + * damages, or other liability, whether in an action of contract, tort, or otherwise, arising + * from, out of, or in connection with the software or the use or other dealings in the software. + * + * Note: This implementation does not utilize OpenSSL or any cryptographic libraries, as + * XORoshiro-256 is not intended for cryptographic applications. It is crucial for applications + * requiring cryptographic security to use a cryptographically secure PRNG. + */ + +#include "xoroshiro256_prng.h" +#include +#include + +void xoroshiro256_init( xoroshiro256_state_t* state, uint64_t init_key[], unsigned long key_length ) +{ + // Initialization logic; ensure 256 bits are properly seeded + for( int i = 0; i < 4; i++ ) + { + if( i < key_length ) + { + state->s[i] = init_key[i]; + } + else + { + // Example fallback for insufficient seeds; consider better seeding strategies + state->s[i] = state->s[i - 1] * 6364136223846793005ULL + 1; + } + } +} + +static inline uint64_t rotl( const uint64_t x, int k ) +{ + return ( x << k ) | ( x >> ( 64 - k ) ); +} + +void xoroshiro256_genrand_uint256_to_buf( xoroshiro256_state_t* state, unsigned char* bufpos ) +{ + // This part of the code updates the state using xoroshiro256**'s algorithm. + const uint64_t result_starstar = rotl( state->s[1] * 5, 7 ) * 9; + const uint64_t t = state->s[1] << 17; + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + + state->s[2] ^= t; + state->s[3] = rotl( state->s[3], 45 ); + + // Note: 'result_starstar' was only used for demonstration purposes and is not part of the + // original Xoroshiro256** specification. Here, we write the complete state into the buffer. + // Ensure that 'bufpos' has enough storage space (256 bits / 32 bytes). + + memcpy( bufpos, state->s, 32 ); // Copies the entire 256-bit (32 bytes) state into 'bufpos' +} diff --git a/src/xor/xoroshiro256_prng.h b/src/xor/xoroshiro256_prng.h new file mode 100644 index 0000000..a7d9232 --- /dev/null +++ b/src/xor/xoroshiro256_prng.h @@ -0,0 +1,44 @@ +/* + * XORoshiro-256 PRNG Definitions + * Author: Fabian Druschke + * Date: 2024-03-13 + * + * This header file contains definitions for the XORoshiro-256 pseudorandom number generator + * (PRNG) implementation. XORoshiro-256 is part of the XORoshiro family of PRNGs, known for + * their simplicity, efficiency, and high-quality pseudorandom number generation suitable for + * a wide range of applications, excluding cryptographic purposes due to its predictable nature. + * + * As the author of this work, I, Fabian Druschke, hereby release this work into the public + * domain. I dedicate any and all copyright interest in this work to the public domain, making + * it free to use for anyone for any purpose without any conditions, unless such conditions are + * required by law. + * + * This software is provided "as is", without warranty of any kind, express or implied, + * including but not limited to the warranties of merchantability, fitness for a particular + * purpose, and noninfringement. In no event shall the authors be liable for any claim, + * damages, or other liability, whether in an action of contract, tort, or otherwise, arising + * from, out of, or in connection with the software or the use or other dealings in the software. + * + * Note: This implementation does not utilize any cryptographic libraries, as XORoshiro-256 is + * not intended for cryptographic applications. It is crucial for applications requiring + * cryptographic security to use a cryptographically secure PRNG. + */ + +#ifndef XOROSHIRO256_PRNG_H +#define XOROSHIRO256_PRNG_H + +#include + +// Structure to store the state of the xoroshiro256** random number generator +typedef struct xoroshiro256_state_s +{ + uint64_t s[4]; +} xoroshiro256_state_t; + +// Initializes the xoroshiro256** random number generator with a seed +void xoroshiro256_init( xoroshiro256_state_t* state, uint64_t init_key[], unsigned long key_length ); + +// Generates a 256-bit random number using xoroshiro256** and stores it directly in the output buffer +void xoroshiro256_genrand_uint256_to_buf( xoroshiro256_state_t* state, unsigned char* bufpos ); + +#endif // XOROSHIRO256_PRNG_H -- cgit v1.2.3